diff --git a/pom.xml b/pom.xml index d14b0bf0..31aba15b 100644 --- a/pom.xml +++ b/pom.xml @@ -42,14 +42,18 @@ 3.27.0 1.10.0 2.14.0 - 2.1.9 + 3.0.4 1.1.13 26.25.0 1.58.0 2.10.1 - 2.13.5 + + 4.4.16 + 4.5.14 + 2.16.0 2.3.1 2.1.0 + 3.0.2 1.9.10 1.5.1 6.2.6.RELEASE @@ -66,7 +70,7 @@ 2022.0.12 1.7.0 3.1.0 - 1.7.36 + 2.0.9 23.10.0 2.2.17 0.10.4 @@ -262,6 +266,11 @@ braintree-java ${braintree.version} + + com.google.code.findbugs + jsr305 + ${jsr305.version} + com.google.code.gson gson @@ -285,6 +294,16 @@ pom import + + org.apache.httpcomponents + httpcore + ${httpcore.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + @@ -296,9 +315,10 @@ test - com.github.tomakehurst - wiremock-jre8 - 2.35.1 + org.wiremock + + wiremock-standalone + 3.3.1 test diff --git a/service/pom.xml b/service/pom.xml index a91bd868..2a6db6b7 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -165,12 +165,6 @@ io.dropwizard dropwizard-testing test - - - junit - junit - - @@ -195,7 +189,7 @@ org.eclipse.jetty.websocket - websocket-api + websocket-jetty-api org.eclipse.jetty @@ -380,12 +374,6 @@ org.glassfish.jersey.test-framework jersey-test-framework-core test - - - junit - junit - - org.glassfish.jersey.test-framework.providers @@ -396,10 +384,6 @@ javax.servlet javax.servlet-api - - junit - junit - diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index e0c15a7d..9ed3446d 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -5,7 +5,7 @@ package org.whispersystems.textsecuregcm; import com.fasterxml.jackson.annotation.JsonProperty; -import io.dropwizard.Configuration; +import io.dropwizard.core.Configuration; import java.time.Duration; import java.util.HashMap; import java.util.HashSet; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 14e42f91..2234c95e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -15,14 +15,14 @@ import com.google.cloud.logging.LoggingOptions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import io.dropwizard.Application; import io.dropwizard.auth.AuthFilter; import io.dropwizard.auth.PolymorphicAuthDynamicFeature; import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; import io.dropwizard.auth.basic.BasicCredentialAuthFilter; import io.dropwizard.auth.basic.BasicCredentials; -import io.dropwizard.setup.Bootstrap; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; import io.grpc.ServerBuilder; import io.grpc.ServerInterceptors; import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder; @@ -50,6 +50,7 @@ import javax.servlet.DispatcherType; import javax.servlet.FilterRegistration; import javax.servlet.ServletRegistration; import org.eclipse.jetty.servlets.CrossOriginFilter; +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; import org.glassfish.jersey.server.ServerProperties; import org.signal.event.AdminEventLogger; import org.signal.event.GoogleCloudAdminEventLogger; @@ -91,11 +92,11 @@ import org.whispersystems.textsecuregcm.configuration.secrets.SecretStore; import org.whispersystems.textsecuregcm.configuration.secrets.SecretsModule; import org.whispersystems.textsecuregcm.controllers.AccountController; import org.whispersystems.textsecuregcm.controllers.AccountControllerV2; +import org.whispersystems.textsecuregcm.controllers.ArchiveController; import org.whispersystems.textsecuregcm.controllers.ArtController; import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV2; import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV3; import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV4; -import org.whispersystems.textsecuregcm.controllers.ArchiveController; import org.whispersystems.textsecuregcm.controllers.CallLinkController; import org.whispersystems.textsecuregcm.controllers.CertificateController; import org.whispersystems.textsecuregcm.controllers.ChallengeController; @@ -706,7 +707,7 @@ public class WhisperServerService extends Application webSocketEnvironment = new WebSocketEnvironment<>(environment, - config.getWebSocketConfiguration(), 90000); + config.getWebSocketConfiguration(), Duration.ofMillis(90000)); webSocketEnvironment.setAuthenticator(new WebSocketAccountAuthenticator(accountAuthenticator)); webSocketEnvironment.setConnectListener( new AuthenticatedConnectListener(receiptSender, messagesManager, pushNotificationManager, @@ -826,7 +827,7 @@ public class WhisperServerService extends Application provisioningEnvironment = new WebSocketEnvironment<>(environment, - webSocketEnvironment.getRequestLog(), 60000); + webSocketEnvironment.getRequestLog(), Duration.ofMillis(60000)); provisioningEnvironment.jersey().register(new WebsocketRefreshApplicationEventListener(accountsManager, clientPresenceManager)); provisioningEnvironment.setConnectListener(new ProvisioningConnectListener(provisioningManager)); provisioningEnvironment.jersey().register(new MetricsApplicationEventListener(TrafficSource.WEBSOCKET, clientReleaseManager)); @@ -840,6 +841,8 @@ public class WhisperServerService extends Application webSocketServlet = new WebSocketResourceProviderFactory<>( webSocketEnvironment, AuthenticatedAccount.class, config.getWebSocketConfiguration()); WebSocketResourceProviderFactory provisioningServlet = new WebSocketResourceProviderFactory<>( diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/GcpAttachmentsConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/GcpAttachmentsConfiguration.java index fba253e6..8c075e25 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/GcpAttachmentsConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/GcpAttachmentsConfiguration.java @@ -5,11 +5,11 @@ package org.whispersystems.textsecuregcm.configuration; -import io.dropwizard.util.Strings; import io.dropwizard.validation.ValidationMethod; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import org.apache.commons.lang3.StringUtils; import org.whispersystems.textsecuregcm.configuration.secrets.SecretString; public record GcpAttachmentsConfiguration(@NotBlank String domain, @@ -20,6 +20,6 @@ public record GcpAttachmentsConfiguration(@NotBlank String domain, @SuppressWarnings("unused") @ValidationMethod(message = "pathPrefix must be empty or start with /") public boolean isPathPrefixValid() { - return Strings.isNullOrEmpty(pathPrefix) || pathPrefix.startsWith("/"); + return StringUtils.isEmpty(pathPrefix) || pathPrefix.startsWith("/"); } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/gcp/CanonicalRequestGenerator.java b/service/src/main/java/org/whispersystems/textsecuregcm/gcp/CanonicalRequestGenerator.java index d530bf88..926db0a7 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/gcp/CanonicalRequestGenerator.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/gcp/CanonicalRequestGenerator.java @@ -5,9 +5,6 @@ package org.whispersystems.textsecuregcm.gcp; -import io.dropwizard.util.Strings; - -import javax.annotation.Nonnull; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Duration; @@ -16,6 +13,8 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.Locale; +import javax.annotation.Nonnull; +import org.apache.commons.lang3.StringUtils; public class CanonicalRequestGenerator { private static final DateTimeFormatter SIMPLE_UTC_DATE = DateTimeFormatter.ofPattern("yyyyMMdd", Locale.US).withZone(ZoneOffset.UTC); @@ -43,7 +42,7 @@ public class CanonicalRequestGenerator { final StringBuilder result = new StringBuilder("POST\n"); final StringBuilder resourcePathBuilder = new StringBuilder(); - if (!Strings.isNullOrEmpty(pathPrefix)) { + if (StringUtils.isNotEmpty(pathPrefix)) { resourcePathBuilder.append(pathPrefix); } resourcePathBuilder.append('/').append(URLEncoder.encode(key, StandardCharsets.UTF_8)); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/LogstashTcpSocketAppenderFactory.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/LogstashTcpSocketAppenderFactory.java index aa94b2e4..028d34ab 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/LogstashTcpSocketAppenderFactory.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/LogstashTcpSocketAppenderFactory.java @@ -17,10 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; -import io.dropwizard.logging.AbstractAppenderFactory; -import io.dropwizard.logging.async.AsyncAppenderFactory; -import io.dropwizard.logging.filter.LevelFilterFactory; -import io.dropwizard.logging.layout.LayoutFactory; +import io.dropwizard.logging.common.AbstractAppenderFactory; +import io.dropwizard.logging.common.async.AsyncAppenderFactory; +import io.dropwizard.logging.common.filter.LevelFilterFactory; +import io.dropwizard.logging.common.layout.LayoutFactory; import java.time.Duration; import java.util.Optional; import javax.validation.constraints.NotEmpty; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsUtil.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsUtil.java index d1e2af7d..416f8339 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsUtil.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/MetricsUtil.java @@ -7,7 +7,7 @@ package org.whispersystems.textsecuregcm.metrics; import com.codahale.metrics.SharedMetricRegistries; import com.google.common.annotations.VisibleForTesting; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.setup.Environment; import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Metrics; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/SignalDatadogReporterFactory.java b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/SignalDatadogReporterFactory.java index 0a4920af..3d604909 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/metrics/SignalDatadogReporterFactory.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/metrics/SignalDatadogReporterFactory.java @@ -14,7 +14,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.ScheduledReporter; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; -import io.dropwizard.metrics.BaseReporterFactory; +import io.dropwizard.metrics.common.BaseReporterFactory; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/util/logging/RequestLogEnabledFilterFactory.java b/service/src/main/java/org/whispersystems/textsecuregcm/util/logging/RequestLogEnabledFilterFactory.java index 7de34182..6371d9ec 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/util/logging/RequestLogEnabledFilterFactory.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/util/logging/RequestLogEnabledFilterFactory.java @@ -8,7 +8,7 @@ package org.whispersystems.textsecuregcm.util.logging; import ch.qos.logback.access.spi.IAccessEvent; import ch.qos.logback.core.filter.Filter; import com.fasterxml.jackson.annotation.JsonTypeName; -import io.dropwizard.logging.filter.FilterFactory; +import io.dropwizard.logging.common.filter.FilterFactory; @JsonTypeName("requestLogEnabled") class RequestLogEnabledFilterFactory implements FilterFactory { diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/AbstractSinglePassCrawlAccountsCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/AbstractSinglePassCrawlAccountsCommand.java index 35170555..4251a91a 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/AbstractSinglePassCrawlAccountsCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/AbstractSinglePassCrawlAccountsCommand.java @@ -5,10 +5,10 @@ package org.whispersystems.textsecuregcm.workers; -import io.dropwizard.Application; -import io.dropwizard.cli.Cli; -import io.dropwizard.cli.EnvironmentCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.Cli; +import io.dropwizard.core.cli.EnvironmentCommand; +import io.dropwizard.core.setup.Environment; import java.util.Objects; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/AssignUsernameCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/AssignUsernameCommand.java index 12549f5d..88c79c61 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/AssignUsernameCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/AssignUsernameCommand.java @@ -8,9 +8,9 @@ package org.whispersystems.textsecuregcm.workers; import static com.codahale.metrics.MetricRegistry.name; import com.fasterxml.jackson.databind.DeserializationFeature; -import io.dropwizard.Application; -import io.dropwizard.cli.EnvironmentCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.EnvironmentCommand; +import io.dropwizard.core.setup.Environment; import io.lettuce.core.resource.ClientResources; import java.time.Clock; import java.util.Base64; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java index b54aaae0..eee7f5c2 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java @@ -7,6 +7,11 @@ package org.whispersystems.textsecuregcm.workers; import com.google.common.base.MoreObjects; import com.google.protobuf.ByteString; +import io.dropwizard.core.cli.Command; +import io.dropwizard.core.setup.Bootstrap; +import java.security.InvalidKeyException; +import java.util.Base64; +import java.util.Set; import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; @@ -15,13 +20,6 @@ import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.whispersystems.textsecuregcm.entities.MessageProtos; -import java.security.InvalidKeyException; -import java.util.Base64; -import java.util.Set; - -import io.dropwizard.cli.Command; -import io.dropwizard.setup.Bootstrap; - public class CertificateCommand extends Command { private static final Set RESERVED_CERTIFICATE_IDS = Set.of( diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CheckDynamicConfigurationCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CheckDynamicConfigurationCommand.java index aeaaef82..974390cb 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CheckDynamicConfigurationCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CheckDynamicConfigurationCommand.java @@ -5,8 +5,8 @@ package org.whispersystems.textsecuregcm.workers; -import io.dropwizard.cli.Command; -import io.dropwizard.setup.Bootstrap; +import io.dropwizard.core.cli.Command; +import io.dropwizard.core.setup.Bootstrap; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java index b25d5ab1..a58b137a 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CommandDependencies.java @@ -8,7 +8,7 @@ package org.whispersystems.textsecuregcm.workers; import static com.codahale.metrics.MetricRegistry.name; import com.fasterxml.jackson.databind.DeserializationFeature; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.setup.Environment; import io.lettuce.core.resource.ClientResources; import java.io.IOException; import java.security.cert.CertificateException; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java index 6b58963d..31b0b750 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java @@ -6,9 +6,9 @@ package org.whispersystems.textsecuregcm.workers; import com.fasterxml.jackson.databind.DeserializationFeature; -import io.dropwizard.Application; -import io.dropwizard.cli.EnvironmentCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.EnvironmentCommand; +import io.dropwizard.core.setup.Environment; import java.util.Optional; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/MessagePersisterServiceCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/MessagePersisterServiceCommand.java index e56d2705..624e20d1 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/MessagePersisterServiceCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/MessagePersisterServiceCommand.java @@ -5,9 +5,9 @@ package org.whispersystems.textsecuregcm.workers; -import io.dropwizard.Application; -import io.dropwizard.cli.ServerCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.ServerCommand; +import io.dropwizard.core.setup.Environment; import java.time.Duration; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/ScheduledApnPushNotificationSenderServiceCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/ScheduledApnPushNotificationSenderServiceCommand.java index 6a5e98b9..2e77167f 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/ScheduledApnPushNotificationSenderServiceCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/ScheduledApnPushNotificationSenderServiceCommand.java @@ -7,9 +7,10 @@ package org.whispersystems.textsecuregcm.workers; import static com.codahale.metrics.MetricRegistry.name; -import io.dropwizard.Application; -import io.dropwizard.cli.ServerCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.ServerCommand; +import io.dropwizard.core.setup.Environment; +import java.util.Optional; import java.util.concurrent.ExecutorService; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/ServerVersionCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/ServerVersionCommand.java index efe12a66..9f0b6e03 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/ServerVersionCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/ServerVersionCommand.java @@ -5,8 +5,8 @@ package org.whispersystems.textsecuregcm.workers; -import io.dropwizard.cli.Command; -import io.dropwizard.setup.Bootstrap; +import io.dropwizard.core.cli.Command; +import io.dropwizard.core.setup.Bootstrap; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.whispersystems.textsecuregcm.WhisperServerVersion; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/SetUserDiscoverabilityCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/SetUserDiscoverabilityCommand.java index 0c46a5d0..d3baba76 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/SetUserDiscoverabilityCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/SetUserDiscoverabilityCommand.java @@ -6,9 +6,9 @@ package org.whispersystems.textsecuregcm.workers; import com.fasterxml.jackson.databind.DeserializationFeature; -import io.dropwizard.Application; -import io.dropwizard.cli.EnvironmentCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.EnvironmentCommand; +import io.dropwizard.core.setup.Environment; import java.util.Optional; import java.util.UUID; import net.sourceforge.argparse4j.inf.Namespace; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/UnlinkDeviceCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/UnlinkDeviceCommand.java index 21a0f830..9553a04e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/UnlinkDeviceCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/UnlinkDeviceCommand.java @@ -6,9 +6,9 @@ package org.whispersystems.textsecuregcm.workers; import com.fasterxml.jackson.databind.DeserializationFeature; -import io.dropwizard.Application; -import io.dropwizard.cli.EnvironmentCommand; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.cli.EnvironmentCommand; +import io.dropwizard.core.setup.Environment; import java.util.List; import java.util.UUID; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/ZkParamsCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/ZkParamsCommand.java index 3cb85d4d..bce402f6 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/ZkParamsCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/ZkParamsCommand.java @@ -5,15 +5,14 @@ package org.whispersystems.textsecuregcm.workers; +import io.dropwizard.core.cli.Command; +import io.dropwizard.core.setup.Bootstrap; +import java.util.Base64; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import org.signal.libsignal.zkgroup.ServerPublicParams; import org.signal.libsignal.zkgroup.ServerSecretParams; -import io.dropwizard.cli.Command; -import io.dropwizard.setup.Bootstrap; -import java.util.Base64; - public class ZkParamsCommand extends Command { public ZkParamsCommand() { diff --git a/service/src/main/resources/META-INF/services/io.dropwizard.logging.AppenderFactory b/service/src/main/resources/META-INF/services/io.dropwizard.logging.common.AppenderFactory similarity index 100% rename from service/src/main/resources/META-INF/services/io.dropwizard.logging.AppenderFactory rename to service/src/main/resources/META-INF/services/io.dropwizard.logging.common.AppenderFactory diff --git a/service/src/main/resources/META-INF/services/io.dropwizard.logging.filter.FilterFactory b/service/src/main/resources/META-INF/services/io.dropwizard.logging.common.filter.FilterFactory similarity index 100% rename from service/src/main/resources/META-INF/services/io.dropwizard.logging.filter.FilterFactory rename to service/src/main/resources/META-INF/services/io.dropwizard.logging.common.filter.FilterFactory diff --git a/service/src/main/resources/META-INF/services/io.dropwizard.metrics.ReporterFactory b/service/src/main/resources/META-INF/services/io.dropwizard.metrics.common.ReporterFactory similarity index 100% rename from service/src/main/resources/META-INF/services/io.dropwizard.metrics.ReporterFactory rename to service/src/main/resources/META-INF/services/io.dropwizard.metrics.common.ReporterFactory diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java index 3c415416..59687583 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.protobuf.InvalidProtocolBufferException; import io.dropwizard.auth.Auth; import io.dropwizard.auth.PolymorphicAuthDynamicFeature; import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; @@ -28,9 +27,11 @@ import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.Principal; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -57,6 +58,7 @@ import javax.ws.rs.core.Response; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.UpgradeRequest; +import org.eclipse.jetty.websocket.api.WriteCallback; import org.glassfish.jersey.server.ApplicationHandler; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.monitoring.ApplicationEventListener; @@ -337,7 +339,7 @@ class AuthEnablementRefreshRequirementProviderTest { provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, requestLog, new TestPrincipal("test", account, authenticatedDevice), new ProtobufWebSocketMessageFactory(), - Optional.empty(), 30000); + Optional.empty(), Duration.ofMillis(30000)); remoteEndpoint = mock(RemoteEndpoint.class); Session session = mock(Session.class); @@ -363,9 +365,9 @@ class AuthEnablementRefreshRequirementProviderTest { } private SubProtocol.WebSocketResponseMessage verifyAndGetResponse(final RemoteEndpoint remoteEndpoint) - throws InvalidProtocolBufferException { + throws IOException { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); return SubProtocol.WebSocketMessage.parseFrom(responseBytesCaptor.getValue().array()).getResponse(); } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListenerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListenerTest.java index c9aeca5e..f3b1962f 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListenerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/metrics/MetricsRequestEventListenerTest.java @@ -22,8 +22,10 @@ import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; +import java.io.IOException; import java.nio.ByteBuffer; import java.security.Principal; +import java.time.Duration; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; @@ -36,6 +38,7 @@ import javax.ws.rs.Path; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.UpgradeRequest; +import org.eclipse.jetty.websocket.api.WriteCallback; import org.glassfish.jersey.server.ApplicationHandler; import org.glassfish.jersey.server.ContainerRequest; import org.glassfish.jersey.server.ContainerResponse; @@ -121,7 +124,7 @@ class MetricsRequestEventListenerTest { } @Test - void testActualRouteMessageSuccess() throws InvalidProtocolBufferException { + void testActualRouteMessageSuccess() throws IOException { final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class); when(applicationEventListener.onRequest(any())).thenReturn(listener); @@ -140,7 +143,7 @@ class MetricsRequestEventListenerTest { new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), - 30000); + Duration.ofMillis(30000)); final Session session = mock(Session.class); final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -163,7 +166,7 @@ class MetricsRequestEventListenerTest { provider.onWebSocketBinary(message, 0, message.length); final ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -187,7 +190,7 @@ class MetricsRequestEventListenerTest { } @Test - void testActualRouteMessageSuccessNoUserAgent() throws InvalidProtocolBufferException { + void testActualRouteMessageSuccessNoUserAgent() throws IOException { final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class); when(applicationEventListener.onRequest(any())).thenReturn(listener); @@ -200,8 +203,10 @@ class MetricsRequestEventListenerTest { final ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); final WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); - final WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + final WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", + applicationHandler, + requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); final Session session = mock(Session.class); final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -222,7 +227,7 @@ class MetricsRequestEventListenerTest { provider.onWebSocketBinary(message, 0, message.length); final ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java index 25df81c6..12d8ac85 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java @@ -137,7 +137,7 @@ class AccountsManagerTest { //noinspection unchecked asyncCommands = mock(RedisAdvancedClusterAsyncCommands.class); - when(asyncCommands.del(any())).thenReturn(MockRedisFuture.completedFuture(0L)); + when(asyncCommands.del(any(String[].class))).thenReturn(MockRedisFuture.completedFuture(0L)); when(asyncCommands.get(any())).thenReturn(MockRedisFuture.completedFuture(null)); when(asyncCommands.setex(any(), anyLong(), any())).thenReturn(MockRedisFuture.completedFuture("OK")); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java index 9c7e7a55..e5979127 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java @@ -679,7 +679,7 @@ class MessagesCacheTest { pages.add(generatePage()); pages.add(generateStaleEphemeralPage()); - when(reactiveCommands.evalsha(any(), any(), any(), any())) + when(reactiveCommands.evalsha(any(), any(), any(byte[][].class), any(byte[][].class))) .thenReturn(Flux.just(pages.pop())) .thenReturn(Flux.just(pages.pop())) .thenReturn(Flux.just(pages.pop())) @@ -688,7 +688,7 @@ class MessagesCacheTest { final AsyncCommand removeSuccess = new AsyncCommand<>(mock(RedisCommand.class)); removeSuccess.complete(); - when(asyncCommands.evalsha(any(), any(), any(), any())) + when(asyncCommands.evalsha(any(), any(), any(byte[][].class), any(byte[][].class))) .thenReturn((RedisFuture) removeSuccess); final Publisher allMessages = messagesCache.get(UUID.randomUUID(), Device.PRIMARY_ID); @@ -696,9 +696,9 @@ class MessagesCacheTest { StepVerifier.setDefaultTimeout(Duration.ofSeconds(5)); // async commands are used for remove(), and nothing should happen until we are subscribed - verify(asyncCommands, never()).evalsha(any(), any(), any(byte[][].class), any(byte[].class)); + verify(asyncCommands, never()).evalsha(any(), any(), any(byte[][].class), any(byte[][].class)); // the reactive commands will be called once, to prep the first page fetch (but no remote request would actually be sent) - verify(reactiveCommands, times(1)).evalsha(any(), any(), any(byte[][].class), any(byte[].class)); + verify(reactiveCommands, times(1)).evalsha(any(), any(), any(byte[][].class), any(byte[][].class)); StepVerifier.create(allMessages) .expectSubscription() @@ -708,7 +708,7 @@ class MessagesCacheTest { .verify(); assertTrue(pages.isEmpty()); - verify(asyncCommands, atLeast(1)).evalsha(any(), any(), any(), any()); + verify(asyncCommands, atLeast(1)).evalsha(any(), any(), any(byte[][].class), any(byte[][].class)); } private List generatePage() { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/JsonHelpers.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/JsonHelpers.java index fc25c010..c35ee708 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/JsonHelpers.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/JsonHelpers.java @@ -5,12 +5,11 @@ package org.whispersystems.textsecuregcm.tests.util; -import static io.dropwizard.testing.FixtureHelpers.fixture; - import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import io.dropwizard.util.Resources; import org.whispersystems.textsecuregcm.util.SystemMapper; public class JsonHelpers { @@ -26,6 +25,7 @@ public class JsonHelpers { } public static String jsonFixture(String filename) throws IOException { - return objectMapper.writeValueAsString(objectMapper.readValue(fixture(filename), JsonNode.class)); + return objectMapper.writeValueAsString( + objectMapper.readValue(Resources.getResource(filename), JsonNode.class)); } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/RedisClusterHelper.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/RedisClusterHelper.java index e0f8201b..c11dfbb7 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/RedisClusterHelper.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/RedisClusterHelper.java @@ -50,24 +50,6 @@ public class RedisClusterHelper { return null; }).when(cluster).useCluster(any(Consumer.class)); - when(cluster.withCluster(any(Function.class))).thenAnswer(invocation -> { - return invocation.getArgument(0, Function.class).apply(stringConnection); - }); - - doAnswer(invocation -> { - invocation.getArgument(0, Consumer.class).accept(stringConnection); - return null; - }).when(cluster).useCluster(any(Consumer.class)); - - when(cluster.withBinaryCluster(any(Function.class))).thenAnswer(invocation -> { - return invocation.getArgument(0, Function.class).apply(binaryConnection); - }); - - doAnswer(invocation -> { - invocation.getArgument(0, Consumer.class).accept(binaryConnection); - return null; - }).when(cluster).useBinaryCluster(any(Consumer.class)); - when(cluster.withBinaryCluster(any(Function.class))).thenAnswer(invocation -> { return invocation.getArgument(0, Function.class).apply(binaryConnection); }); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/util/logging/LoggingUnhandledExceptionMapperTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/util/logging/LoggingUnhandledExceptionMapperTest.java index 9ac97b4a..e75a7b0a 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/util/logging/LoggingUnhandledExceptionMapperTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/util/logging/LoggingUnhandledExceptionMapperTest.java @@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.util.logging; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.matches; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; @@ -20,8 +21,10 @@ import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; +import java.io.IOException; import java.nio.ByteBuffer; import java.security.Principal; +import java.time.Duration; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -40,6 +43,7 @@ import javax.ws.rs.core.Response; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.UpgradeRequest; +import org.eclipse.jetty.websocket.api.WriteCallback; import org.glassfish.jersey.server.ApplicationHandler; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ServerProperties; @@ -159,7 +163,7 @@ class LoggingUnhandledExceptionMapperTest { } private WebSocketResourceProvider createWebsocketProvider(final String userAgentHeader, - final Session session, final Consumer responseHandler) { + final Session session, final Consumer responseHandler) throws IOException { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(exceptionMapper); resourceConfig.register(new TestController()); @@ -170,14 +174,14 @@ class LoggingUnhandledExceptionMapperTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); - when(remoteEndpoint.sendBytesByFuture(any())) - .thenAnswer(answer -> { - responseHandler.accept(answer.getArgument(0, ByteBuffer.class)); - return CompletableFuture.completedFuture(null); - }); + doAnswer(answer -> { + responseHandler.accept(answer.getArgument(0, ByteBuffer.class)); + return null; + }).when(remoteEndpoint).sendBytes(any(), any(WriteCallback.class)); UpgradeRequest request = mock(UpgradeRequest.class); when(session.getUpgradeRequest()).thenReturn(request); diff --git a/service/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/service/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker deleted file mode 100644 index 1f0955d4..00000000 --- a/service/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +++ /dev/null @@ -1 +0,0 @@ -mock-maker-inline diff --git a/websocket-resources/pom.xml b/websocket-resources/pom.xml index e936977c..0e64c3fd 100644 --- a/websocket-resources/pom.xml +++ b/websocket-resources/pom.xml @@ -13,12 +13,11 @@ org.eclipse.jetty.websocket - websocket-api + websocket-jetty-api org.eclipse.jetty.websocket - websocket-server - runtime + websocket-jetty-server org.eclipse.jetty.websocket @@ -97,11 +96,6 @@ jsr305 - - org.mockito - mockito-inline - test - org.junit.jupiter junit-jupiter diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketClient.java b/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketClient.java index a3dbd33d..6f9efe8d 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketClient.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketClient.java @@ -14,7 +14,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.exceptions.WebSocketException; import org.eclipse.jetty.websocket.api.WriteCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -99,7 +99,7 @@ public class WebSocketClient { public void hardDisconnectQuietly() { try { session.disconnect(); - } catch (IOException e) { + } catch (Exception e) { // quietly we said } } diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProvider.java b/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProvider.java index 738541b5..2ca34905 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProvider.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProvider.java @@ -7,10 +7,28 @@ package org.whispersystems.websocket; import com.google.common.annotations.VisibleForTesting; import com.google.common.net.HttpHeaders; import com.google.protobuf.UninitializedMessageException; -import org.eclipse.jetty.websocket.api.MessageTooLargeException; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.time.Duration; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketListener; +import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.exceptions.MessageTooLargeException; import org.glassfish.jersey.internal.MapPropertiesDelegate; import org.glassfish.jersey.server.ApplicationHandler; import org.glassfish.jersey.server.ContainerRequest; @@ -27,23 +45,6 @@ import org.whispersystems.websocket.session.ContextPrincipal; import org.whispersystems.websocket.session.WebSocketSessionContext; import org.whispersystems.websocket.setup.WebSocketConnectListener; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.URI; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public class WebSocketResourceProvider implements WebSocketListener { @@ -57,44 +58,44 @@ public class WebSocketResourceProvider implements WebSocket private final Map> requestMap = new ConcurrentHashMap<>(); - private final T authenticated; - private final WebSocketMessageFactory messageFactory; + private final T authenticated; + private final WebSocketMessageFactory messageFactory; private final Optional connectListener; - private final ApplicationHandler jerseyHandler; - private final WebsocketRequestLog requestLog; - private final long idleTimeoutMillis; - private final String remoteAddress; + private final ApplicationHandler jerseyHandler; + private final WebsocketRequestLog requestLog; + private final Duration idleTimeout; + private final String remoteAddress; - private Session session; - private RemoteEndpoint remoteEndpoint; + private Session session; + private RemoteEndpoint remoteEndpoint; private WebSocketSessionContext context; private static final Set EXCLUDED_UPGRADE_REQUEST_HEADERS = Set.of("connection", "upgrade"); - public WebSocketResourceProvider(String remoteAddress, - ApplicationHandler jerseyHandler, - WebsocketRequestLog requestLog, - T authenticated, - WebSocketMessageFactory messageFactory, - Optional connectListener, - long idleTimeoutMillis) - { - this.remoteAddress = remoteAddress; - this.jerseyHandler = jerseyHandler; - this.requestLog = requestLog; - this.authenticated = authenticated; - this.messageFactory = messageFactory; - this.connectListener = connectListener; - this.idleTimeoutMillis = idleTimeoutMillis; + public WebSocketResourceProvider(String remoteAddress, + ApplicationHandler jerseyHandler, + WebsocketRequestLog requestLog, + T authenticated, + WebSocketMessageFactory messageFactory, + Optional connectListener, + Duration idleTimeout) { + this.remoteAddress = remoteAddress; + this.jerseyHandler = jerseyHandler; + this.requestLog = requestLog; + this.authenticated = authenticated; + this.messageFactory = messageFactory; + this.connectListener = connectListener; + this.idleTimeout = idleTimeout; } @Override public void onWebSocketConnect(Session session) { - this.session = session; + this.session = session; this.remoteEndpoint = session.getRemote(); - this.context = new WebSocketSessionContext(new WebSocketClient(session, remoteEndpoint, messageFactory, requestMap)); + this.context = new WebSocketSessionContext( + new WebSocketClient(session, remoteEndpoint, messageFactory, requestMap)); this.context.setAuthenticated(authenticated); - this.session.setIdleTimeout(idleTimeoutMillis); + this.session.setIdleTimeout(idleTimeout); connectListener.ifPresent(listener -> listener.onWebSocketConnect(this.context)); } @@ -129,12 +130,12 @@ public class WebSocketResourceProvider implements WebSocket handleResponse(webSocketMessage.getResponseMessage()); break; default: - close(session, 1018, "Badly formatted"); + close(session, 1007, "Badly formatted"); break; } } catch (UninitializedMessageException | InvalidMessageException e) { logger.debug("Parsing", e); - close(session, 1018, "Badly formatted"); + close(session, 1007, "Badly formatted"); } } @@ -159,23 +160,36 @@ public class WebSocketResourceProvider implements WebSocket } private void handleRequest(WebSocketRequestMessage requestMessage) { - ContainerRequest containerRequest = new ContainerRequest(null, URI.create(requestMessage.getPath()), requestMessage.getVerb(), new WebSocketSecurityContext(new ContextPrincipal(context)), new MapPropertiesDelegate(new HashMap<>()), jerseyHandler.getConfiguration()); + ContainerRequest containerRequest = new ContainerRequest(null, URI.create(requestMessage.getPath()), + requestMessage.getVerb(), new WebSocketSecurityContext(new ContextPrincipal(context)), + new MapPropertiesDelegate(new HashMap<>()), jerseyHandler.getConfiguration()); containerRequest.headers(getCombinedHeaders(session.getUpgradeRequest().getHeaders(), requestMessage.getHeaders())); if (requestMessage.getBody().isPresent()) { containerRequest.setEntityStream(new ByteArrayInputStream(requestMessage.getBody().get())); } - ByteArrayOutputStream responseBody = new ByteArrayOutputStream(); - CompletableFuture responseFuture = (CompletableFuture) jerseyHandler.apply(containerRequest, responseBody); + ByteArrayOutputStream responseBody = new ByteArrayOutputStream(); + CompletableFuture responseFuture = (CompletableFuture) jerseyHandler.apply( + containerRequest, responseBody); responseFuture.thenAccept(response -> { - sendResponse(requestMessage, response, responseBody); + try { + sendResponse(requestMessage, response, responseBody); + } catch (IOException e) { + throw new RuntimeException(e); + } requestLog.log(remoteAddress, containerRequest, response); }).exceptionally(exception -> { - logger.warn("Websocket Error: " + requestMessage.getVerb() + " " + requestMessage.getPath() + "\n" + requestMessage.getBody(), exception); - sendErrorResponse(requestMessage, Response.status(500).build()); - requestLog.log(remoteAddress, containerRequest, new ContainerResponse(containerRequest, Response.status(500).build())); + logger.warn("Websocket Error: " + requestMessage.getVerb() + " " + requestMessage.getPath() + "\n" + + requestMessage.getBody(), exception); + try { + sendErrorResponse(requestMessage, Response.status(500).build()); + } catch (IOException e) { + logger.warn("Failed to send error response", e); + } + requestLog.log(remoteAddress, containerRequest, + new ContainerResponse(containerRequest, Response.status(500).build())); return null; }); } @@ -217,7 +231,8 @@ public class WebSocketResourceProvider implements WebSocket session.close(status, message); } - private void sendResponse(WebSocketRequestMessage requestMessage, ContainerResponse response, ByteArrayOutputStream responseBody) { + private void sendResponse(WebSocketRequestMessage requestMessage, ContainerResponse response, + ByteArrayOutputStream responseBody) throws IOException { if (requestMessage.hasRequestId()) { byte[] body = responseBody.toByteArray(); @@ -226,25 +241,25 @@ public class WebSocketResourceProvider implements WebSocket } byte[] responseBytes = messageFactory.createResponse(requestMessage.getRequestId(), - response.getStatus(), - response.getStatusInfo().getReasonPhrase(), - getHeaderList(response.getStringHeaders()), - Optional.ofNullable(body)) - .toByteArray(); + response.getStatus(), + response.getStatusInfo().getReasonPhrase(), + getHeaderList(response.getStringHeaders()), + Optional.ofNullable(body)) + .toByteArray(); - remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(responseBytes)); + remoteEndpoint.sendBytes(ByteBuffer.wrap(responseBytes), WriteCallback.NOOP); } } - private void sendErrorResponse(WebSocketRequestMessage requestMessage, Response error) { + private void sendErrorResponse(WebSocketRequestMessage requestMessage, Response error) throws IOException { if (requestMessage.hasRequestId()) { WebSocketMessage response = messageFactory.createResponse(requestMessage.getRequestId(), - error.getStatus(), - "Error response", - getHeaderList(error.getStringHeaders()), - Optional.empty()); + error.getStatus(), + "Error response", + getHeaderList(error.getStringHeaders()), + Optional.empty()); - remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(response.toByteArray())); + remoteEndpoint.sendBytes(ByteBuffer.wrap(response.toByteArray()), WriteCallback.NOOP); } } diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProviderFactory.java b/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProviderFactory.java index 4cc2a225..b60faa22 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProviderFactory.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProviderFactory.java @@ -9,14 +9,15 @@ import static java.util.Optional.ofNullable; import com.google.common.net.HttpHeaders; import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider; import java.io.IOException; +import java.net.InetSocketAddress; import java.security.Principal; import java.util.Arrays; import java.util.Optional; -import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; -import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; -import org.eclipse.jetty.websocket.servlet.WebSocketCreator; -import org.eclipse.jetty.websocket.servlet.WebSocketServlet; -import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; +import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest; +import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse; +import org.eclipse.jetty.websocket.server.JettyWebSocketCreator; +import org.eclipse.jetty.websocket.server.JettyWebSocketServlet; +import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory; import org.glassfish.jersey.server.ApplicationHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,8 @@ import org.whispersystems.websocket.configuration.WebSocketConfiguration; import org.whispersystems.websocket.session.WebSocketSessionContextValueFactoryProvider; import org.whispersystems.websocket.setup.WebSocketEnvironment; -public class WebSocketResourceProviderFactory extends WebSocketServlet implements WebSocketCreator { +public class WebSocketResourceProviderFactory extends JettyWebSocketServlet implements + JettyWebSocketCreator { private static final Logger logger = LoggerFactory.getLogger(WebSocketResourceProviderFactory.class); @@ -50,10 +52,10 @@ public class WebSocketResourceProviderFactory extends WebSo } @Override - public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) { + public Object createWebSocket(final JettyServerUpgradeRequest request, final JettyServerUpgradeResponse response) { try { Optional> authenticator = Optional.ofNullable(environment.getAuthenticator()); - T authenticated = null; + T authenticated = null; if (authenticator.isPresent()) { AuthenticationResult authenticationResult = authenticator.get().authenticate(request); @@ -72,7 +74,7 @@ public class WebSocketResourceProviderFactory extends WebSo authenticated, this.environment.getMessageFactory(), ofNullable(this.environment.getConnectListener()), - this.environment.getIdleTimeoutMillis()); + this.environment.getIdleTimeout()); } catch (AuthenticationException | IOException e) { logger.warn("Authentication failure", e); try { @@ -84,20 +86,23 @@ public class WebSocketResourceProviderFactory extends WebSo } @Override - public void configure(WebSocketServletFactory factory) { + public void configure(JettyWebSocketServletFactory factory) { factory.setCreator(this); - factory.getPolicy().setMaxBinaryMessageSize(configuration.getMaxBinaryMessageSize()); - factory.getPolicy().setMaxTextMessageSize(configuration.getMaxTextMessageSize()); + factory.setMaxBinaryMessageSize(configuration.getMaxBinaryMessageSize()); + factory.setMaxTextMessageSize(configuration.getMaxTextMessageSize()); } - private String getRemoteAddress(ServletUpgradeRequest request) { + private String getRemoteAddress(JettyServerUpgradeRequest request) { String forwardedFor = request.getHeader(HttpHeaders.X_FORWARDED_FOR); if (forwardedFor == null || forwardedFor.isBlank()) { - return request.getRemoteAddress(); + if (request.getRemoteSocketAddress() instanceof InetSocketAddress inetSocketAddress) { + return inetSocketAddress.getAddress().getHostAddress(); + } + return null; } else { return Arrays.stream(forwardedFor.split(",")) - .map(String::trim) + .map(String::trim) .reduce((a, b) -> b) .orElseThrow(); } diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/auth/WebSocketAuthenticator.java b/websocket-resources/src/main/java/org/whispersystems/websocket/auth/WebSocketAuthenticator.java index 4c913fe8..a8fee10b 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/auth/WebSocketAuthenticator.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/auth/WebSocketAuthenticator.java @@ -9,6 +9,7 @@ import java.util.Optional; import org.eclipse.jetty.websocket.api.UpgradeRequest; public interface WebSocketAuthenticator { + AuthenticationResult authenticate(UpgradeRequest request) throws AuthenticationException; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/AsyncWebsocketEventAppenderFactory.java b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/AsyncWebsocketEventAppenderFactory.java index 2d0399de..4b0b336f 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/AsyncWebsocketEventAppenderFactory.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/AsyncWebsocketEventAppenderFactory.java @@ -5,7 +5,7 @@ package org.whispersystems.websocket.logging; import ch.qos.logback.core.AsyncAppenderBase; -import io.dropwizard.logging.async.AsyncAppenderFactory; +import io.dropwizard.logging.common.async.AsyncAppenderFactory; public class AsyncWebsocketEventAppenderFactory implements AsyncAppenderFactory { @Override diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/WebsocketRequestLoggerFactory.java b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/WebsocketRequestLoggerFactory.java index 69773939..b8a17f82 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/WebsocketRequestLoggerFactory.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/WebsocketRequestLoggerFactory.java @@ -15,12 +15,12 @@ import java.util.List; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; -import io.dropwizard.logging.AppenderFactory; -import io.dropwizard.logging.ConsoleAppenderFactory; -import io.dropwizard.logging.async.AsyncAppenderFactory; -import io.dropwizard.logging.filter.LevelFilterFactory; -import io.dropwizard.logging.filter.NullLevelFilterFactory; -import io.dropwizard.logging.layout.LayoutFactory; +import io.dropwizard.logging.common.AppenderFactory; +import io.dropwizard.logging.common.ConsoleAppenderFactory; +import io.dropwizard.logging.common.async.AsyncAppenderFactory; +import io.dropwizard.logging.common.filter.LevelFilterFactory; +import io.dropwizard.logging.common.filter.NullLevelFilterFactory; +import io.dropwizard.logging.common.layout.LayoutFactory; public class WebsocketRequestLoggerFactory { diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/WebsocketEventLayoutFactory.java b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/WebsocketEventLayoutFactory.java index 8013d38d..66d7c156 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/WebsocketEventLayoutFactory.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/WebsocketEventLayoutFactory.java @@ -6,7 +6,7 @@ package org.whispersystems.websocket.logging.layout; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.core.pattern.PatternLayoutBase; -import io.dropwizard.logging.layout.LayoutFactory; +import io.dropwizard.logging.common.layout.LayoutFactory; import org.whispersystems.websocket.logging.WebsocketEvent; import java.util.TimeZone; diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/converters/DateConverter.java b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/converters/DateConverter.java index abbf27ce..19fcf0da 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/converters/DateConverter.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/logging/layout/converters/DateConverter.java @@ -6,10 +6,10 @@ package org.whispersystems.websocket.logging.layout.converters; import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.util.CachingDateFormatter; -import org.whispersystems.websocket.logging.WebsocketEvent; - +import java.time.ZoneId; import java.util.List; -import java.util.TimeZone; +import java.util.Optional; +import org.whispersystems.websocket.logging.WebsocketEvent; public class DateConverter extends WebSocketEventConverter { @@ -28,7 +28,15 @@ public class DateConverter extends WebSocketEventConverter { } try { - cachingDateFormatter = new CachingDateFormatter(datePattern); + List optionList = getOptionList(); + + Optional timeZone = Optional.empty(); + // if the option list contains a TZ option, then set it. + if (optionList != null && optionList.size() > 1) { + timeZone = Optional.of(ZoneId.of((String) optionList.get(1))); + } + + cachingDateFormatter = new CachingDateFormatter(datePattern, timeZone.orElse(null)); // maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern); } catch (IllegalArgumentException e) { addWarn("Could not instantiate SimpleDateFormat with pattern " + datePattern, e); @@ -36,13 +44,7 @@ public class DateConverter extends WebSocketEventConverter { cachingDateFormatter = new CachingDateFormatter(CoreConstants.CLF_DATE_PATTERN); } - List optionList = getOptionList(); - // if the option list contains a TZ option, then set it. - if (optionList != null && optionList.size() > 1) { - TimeZone tz = TimeZone.getTimeZone((String) optionList.get(1)); - cachingDateFormatter.setTimeZone(tz); - } } @Override diff --git a/websocket-resources/src/main/java/org/whispersystems/websocket/setup/WebSocketEnvironment.java b/websocket-resources/src/main/java/org/whispersystems/websocket/setup/WebSocketEnvironment.java index 64413b38..f344a493 100644 --- a/websocket-resources/src/main/java/org/whispersystems/websocket/setup/WebSocketEnvironment.java +++ b/websocket-resources/src/main/java/org/whispersystems/websocket/setup/WebSocketEnvironment.java @@ -6,7 +6,8 @@ package org.whispersystems.websocket.setup; import com.fasterxml.jackson.databind.ObjectMapper; import io.dropwizard.jersey.DropwizardResourceConfig; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.setup.Environment; +import java.time.Duration; import org.glassfish.jersey.server.ResourceConfig; import org.whispersystems.websocket.auth.WebSocketAuthenticator; import org.whispersystems.websocket.configuration.WebSocketConfiguration; @@ -19,31 +20,31 @@ import java.security.Principal; public class WebSocketEnvironment { - private final ResourceConfig jerseyConfig; - private final ObjectMapper objectMapper; - private final Validator validator; - private final WebsocketRequestLog requestLog; - private final long idleTimeoutMillis; + private final ResourceConfig jerseyConfig; + private final ObjectMapper objectMapper; + private final Validator validator; + private final WebsocketRequestLog requestLog; + private final Duration idleTimeout; private WebSocketAuthenticator authenticator; - private WebSocketMessageFactory messageFactory; - private WebSocketConnectListener connectListener; + private WebSocketMessageFactory messageFactory; + private WebSocketConnectListener connectListener; public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration) { - this(environment, configuration, 60000); + this(environment, configuration, Duration.ofMillis(60000)); } - public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration, long idleTimeoutMillis) { - this(environment, configuration.getRequestLog().build("websocket"), idleTimeoutMillis); + public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration, Duration idleTimeout) { + this(environment, configuration.getRequestLog().build("websocket"), idleTimeout); } - public WebSocketEnvironment(Environment environment, WebsocketRequestLog requestLog, long idleTimeoutMillis) { - this.jerseyConfig = new DropwizardResourceConfig(environment.metrics()); - this.objectMapper = environment.getObjectMapper(); - this.validator = environment.getValidator(); - this.requestLog = requestLog; - this.messageFactory = new ProtobufWebSocketMessageFactory(); - this.idleTimeoutMillis = idleTimeoutMillis; + public WebSocketEnvironment(Environment environment, WebsocketRequestLog requestLog, Duration idleTimeout) { + this.jerseyConfig = new DropwizardResourceConfig(environment.metrics()); + this.objectMapper = environment.getObjectMapper(); + this.validator = environment.getValidator(); + this.requestLog = requestLog; + this.messageFactory = new ProtobufWebSocketMessageFactory(); + this.idleTimeout = idleTimeout; } public ResourceConfig jersey() { @@ -58,8 +59,8 @@ public class WebSocketEnvironment { this.authenticator = authenticator; } - public long getIdleTimeoutMillis() { - return idleTimeoutMillis; + public Duration getIdleTimeout() { + return idleTimeout; } public ObjectMapper getObjectMapper() { diff --git a/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderFactoryTest.java b/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderFactoryTest.java index 33baf6e2..fe76b4fa 100644 --- a/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderFactoryTest.java +++ b/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderFactoryTest.java @@ -20,10 +20,9 @@ import java.util.Optional; import javax.security.auth.Subject; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.UpgradeRequest; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; -import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; -import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; +import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest; +import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse; +import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory; import org.glassfish.jersey.server.ResourceConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,8 +36,8 @@ public class WebSocketResourceProviderFactoryTest { private ResourceConfig jerseyEnvironment; private WebSocketEnvironment environment; private WebSocketAuthenticator authenticator; - private ServletUpgradeRequest request; - private ServletUpgradeResponse response; + private JettyServerUpgradeRequest request; + private JettyServerUpgradeResponse response; @BeforeEach void setup() { @@ -47,8 +46,8 @@ public class WebSocketResourceProviderFactoryTest { environment = mock(WebSocketEnvironment.class); //noinspection unchecked authenticator = mock(WebSocketAuthenticator.class); - request = mock(ServletUpgradeRequest.class); - response = mock(ServletUpgradeResponse.class); + request = mock(JettyServerUpgradeRequest.class); + response = mock(JettyServerUpgradeResponse.class); } @@ -111,9 +110,8 @@ public class WebSocketResourceProviderFactoryTest { @Test void testConfigure() { - WebSocketServletFactory servletFactory = mock(WebSocketServletFactory.class); + JettyWebSocketServletFactory servletFactory = mock(JettyWebSocketServletFactory.class); when(environment.jersey()).thenReturn(jerseyEnvironment); - when(servletFactory.getPolicy()).thenReturn(mock(WebSocketPolicy.class)); WebSocketResourceProviderFactory factory = new WebSocketResourceProviderFactory<>(environment, Account.class, diff --git a/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderTest.java b/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderTest.java index 5bfcfe0b..6feba40e 100644 --- a/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderTest.java +++ b/websocket-resources/src/test/java/org/whispersystems/websocket/WebSocketResourceProviderTest.java @@ -11,21 +11,21 @@ import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.net.HttpHeaders; import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; import io.dropwizard.auth.Auth; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider; import java.io.OutputStream; import java.nio.ByteBuffer; import java.security.Principal; +import java.time.Duration; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -80,7 +80,7 @@ class WebSocketResourceProviderTest { new TestPrincipal("fooz"), new ProtobufWebSocketMessageFactory(), Optional.of(connectListener), - 30000); + Duration.ofMillis(30000)); Session session = mock(Session.class); UpgradeRequest request = mock(UpgradeRequest.class); @@ -105,7 +105,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = mock(ApplicationHandler.class); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -164,7 +165,7 @@ class WebSocketResourceProviderTest { assertThat(bundledRequest.getPath(false)).isEqualTo("bar"); verify(requestLog).log(eq("127.0.0.1"), eq(bundledRequest), eq(response)); - verify(remoteEndpoint).sendBytesByFuture(responseCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom( responseCaptor.getValue().array()); @@ -180,7 +181,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = mock(ApplicationHandler.class); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -215,7 +217,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom( responseCaptor.getValue().array()); @@ -225,7 +227,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageSuccess() throws InvalidProtocolBufferException { + void testActualRouteMessageSuccess() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -235,7 +237,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -253,7 +256,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -264,7 +267,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageNotFound() throws InvalidProtocolBufferException { + void testActualRouteMessageNotFound() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -274,7 +277,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -292,7 +296,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -303,7 +307,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageAuthorized() throws InvalidProtocolBufferException { + void testActualRouteMessageAuthorized() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -314,7 +318,7 @@ class WebSocketResourceProviderTest { WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, requestLog, new TestPrincipal("authorizedUserName"), new ProtobufWebSocketMessageFactory(), Optional.empty(), - 30000); + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -332,7 +336,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -343,7 +347,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageUnauthorized() throws InvalidProtocolBufferException { + void testActualRouteMessageUnauthorized() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -353,7 +357,7 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -371,7 +375,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -381,7 +385,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageOptionalAuthorizedPresent() throws InvalidProtocolBufferException { + void testActualRouteMessageOptionalAuthorizedPresent() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -391,7 +395,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("something"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("something"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -409,7 +414,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -420,7 +425,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageOptionalAuthorizedEmpty() throws InvalidProtocolBufferException { + void testActualRouteMessageOptionalAuthorizedEmpty() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -430,7 +435,7 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -448,7 +453,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -459,7 +464,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessagePutAuthenticatedEntity() throws InvalidProtocolBufferException, JsonProcessingException { + void testActualRouteMessagePutAuthenticatedEntity() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -469,7 +474,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -488,7 +494,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -499,8 +505,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessagePutAuthenticatedBadEntity() - throws InvalidProtocolBufferException, JsonProcessingException { + void testActualRouteMessagePutAuthenticatedBadEntity() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder()); @@ -510,7 +515,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -529,7 +535,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -540,7 +546,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteMessageExceptionMapping() throws InvalidProtocolBufferException { + void testActualRouteMessageExceptionMapping() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new TestExceptionMapper()); @@ -551,7 +557,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -569,7 +576,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -579,7 +586,7 @@ class WebSocketResourceProviderTest { } @Test - void testActualRouteSessionContextInjection() throws InvalidProtocolBufferException { + void testActualRouteSessionContextInjection() throws Exception { ResourceConfig resourceConfig = new DropwizardResourceConfig(); resourceConfig.register(new TestResource()); resourceConfig.register(new TestExceptionMapper()); @@ -590,7 +597,8 @@ class WebSocketResourceProviderTest { ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig); WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class); WebSocketResourceProvider provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler, - requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000); + requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), + Duration.ofMillis(30000)); Session session = mock(Session.class); RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class); @@ -622,7 +630,7 @@ class WebSocketResourceProviderTest { ArgumentCaptor responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture()); + verify(remoteEndpoint, times(2)).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class)); SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor); @@ -690,12 +698,12 @@ class WebSocketResourceProviderTest { } private SubProtocol.WebSocketResponseMessage getResponse(ArgumentCaptor responseCaptor) - throws InvalidProtocolBufferException { + throws Exception { return SubProtocol.WebSocketMessage.parseFrom(responseCaptor.getValue().array()).getResponse(); } private SubProtocol.WebSocketRequestMessage getRequest(ArgumentCaptor requestCaptor) - throws InvalidProtocolBufferException { + throws Exception { return SubProtocol.WebSocketMessage.parseFrom(requestCaptor.getValue().array()).getRequest(); } diff --git a/websocket-resources/src/test/java/org/whispersystems/websocket/logging/WebSocketRequestLogTest.java b/websocket-resources/src/test/java/org/whispersystems/websocket/logging/WebSocketRequestLogTest.java index dd4b8fea..cb8ed859 100644 --- a/websocket-resources/src/test/java/org/whispersystems/websocket/logging/WebSocketRequestLogTest.java +++ b/websocket-resources/src/test/java/org/whispersystems/websocket/logging/WebSocketRequestLogTest.java @@ -11,7 +11,7 @@ import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.core.OutputStreamAppender; import ch.qos.logback.core.spi.DeferredProcessingAware; import com.google.common.net.HttpHeaders; -import io.dropwizard.logging.AbstractOutputStreamAppenderFactory; +import io.dropwizard.logging.common.AbstractOutputStreamAppenderFactory; import java.io.ByteArrayOutputStream; import java.net.URI; import java.util.ArrayList;