Upgrade to dropwizard 3.0
This commit is contained in:
parent
041aa8639a
commit
84b56ae1b2
32
pom.xml
32
pom.xml
|
@ -42,14 +42,18 @@
|
||||||
<braintree.version>3.27.0</braintree.version>
|
<braintree.version>3.27.0</braintree.version>
|
||||||
<commons-csv.version>1.10.0</commons-csv.version>
|
<commons-csv.version>1.10.0</commons-csv.version>
|
||||||
<commons-io.version>2.14.0</commons-io.version>
|
<commons-io.version>2.14.0</commons-io.version>
|
||||||
<dropwizard.version>2.1.9</dropwizard.version>
|
<dropwizard.version>3.0.4</dropwizard.version>
|
||||||
<dropwizard-metrics-datadog.version>1.1.13</dropwizard-metrics-datadog.version>
|
<dropwizard-metrics-datadog.version>1.1.13</dropwizard-metrics-datadog.version>
|
||||||
<google-cloud-libraries.version>26.25.0</google-cloud-libraries.version>
|
<google-cloud-libraries.version>26.25.0</google-cloud-libraries.version>
|
||||||
<grpc.version>1.58.0</grpc.version> <!-- should be kept in sync with the value from Google libraries-bom -->
|
<grpc.version>1.58.0</grpc.version> <!-- should be kept in sync with the value from Google libraries-bom -->
|
||||||
<gson.version>2.10.1</gson.version>
|
<gson.version>2.10.1</gson.version>
|
||||||
<jackson.version>2.13.5</jackson.version>
|
<!-- several libraries (AWS, Google Cloud) use Apache http components transitively, and we need to align them -->
|
||||||
|
<httpcore.version>4.4.16</httpcore.version>
|
||||||
|
<httpclient.version>4.5.14</httpclient.version>
|
||||||
|
<jackson.version>2.16.0</jackson.version>
|
||||||
<jaxb.version>2.3.1</jaxb.version>
|
<jaxb.version>2.3.1</jaxb.version>
|
||||||
<junit-pioneer.version>2.1.0</junit-pioneer.version>
|
<junit-pioneer.version>2.1.0</junit-pioneer.version>
|
||||||
|
<jsr305.version>3.0.2</jsr305.version>
|
||||||
<kotlin.version>1.9.10</kotlin.version>
|
<kotlin.version>1.9.10</kotlin.version>
|
||||||
<kotlinx-serialization.version>1.5.1</kotlinx-serialization.version>
|
<kotlinx-serialization.version>1.5.1</kotlinx-serialization.version>
|
||||||
<lettuce.version>6.2.6.RELEASE</lettuce.version>
|
<lettuce.version>6.2.6.RELEASE</lettuce.version>
|
||||||
|
@ -66,7 +70,7 @@
|
||||||
<reactor-bom.version>2022.0.12</reactor-bom.version> <!-- 3.5.x, see https://github.com/reactor/reactor#bom-versioning-scheme -->
|
<reactor-bom.version>2022.0.12</reactor-bom.version> <!-- 3.5.x, see https://github.com/reactor/reactor#bom-versioning-scheme -->
|
||||||
<resilience4j.version>1.7.0</resilience4j.version>
|
<resilience4j.version>1.7.0</resilience4j.version>
|
||||||
<semver4j.version>3.1.0</semver4j.version>
|
<semver4j.version>3.1.0</semver4j.version>
|
||||||
<slf4j.version>1.7.36</slf4j.version>
|
<slf4j.version>2.0.9</slf4j.version>
|
||||||
<stripe.version>23.10.0</stripe.version>
|
<stripe.version>23.10.0</stripe.version>
|
||||||
<swagger.version>2.2.17</swagger.version>
|
<swagger.version>2.2.17</swagger.version>
|
||||||
<vavr.version>0.10.4</vavr.version>
|
<vavr.version>0.10.4</vavr.version>
|
||||||
|
@ -262,6 +266,11 @@
|
||||||
<artifactId>braintree-java</artifactId>
|
<artifactId>braintree-java</artifactId>
|
||||||
<version>${braintree.version}</version>
|
<version>${braintree.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
|
<artifactId>jsr305</artifactId>
|
||||||
|
<version>${jsr305.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
|
@ -285,6 +294,16 @@
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpcore</artifactId>
|
||||||
|
<version>${httpcore.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>${httpclient.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
@ -296,9 +315,10 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.tomakehurst</groupId>
|
<groupId>org.wiremock</groupId>
|
||||||
<artifactId>wiremock-jre8</artifactId>
|
<!-- use standalone until Dropwizard 4 + jakarta.* -->
|
||||||
<version>2.35.1</version>
|
<artifactId>wiremock-standalone</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
|
|
@ -165,12 +165,6 @@
|
||||||
<groupId>io.dropwizard</groupId>
|
<groupId>io.dropwizard</groupId>
|
||||||
<artifactId>dropwizard-testing</artifactId>
|
<artifactId>dropwizard-testing</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -195,7 +189,7 @@
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
<artifactId>websocket-api</artifactId>
|
<artifactId>websocket-jetty-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
@ -380,12 +374,6 @@
|
||||||
<groupId>org.glassfish.jersey.test-framework</groupId>
|
<groupId>org.glassfish.jersey.test-framework</groupId>
|
||||||
<artifactId>jersey-test-framework-core</artifactId>
|
<artifactId>jersey-test-framework-core</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||||
|
@ -396,10 +384,6 @@
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
package org.whispersystems.textsecuregcm;
|
package org.whispersystems.textsecuregcm;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import io.dropwizard.Configuration;
|
import io.dropwizard.core.Configuration;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
|
@ -15,14 +15,14 @@ import com.google.cloud.logging.LoggingOptions;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import io.dropwizard.Application;
|
|
||||||
import io.dropwizard.auth.AuthFilter;
|
import io.dropwizard.auth.AuthFilter;
|
||||||
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
|
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
|
||||||
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
|
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
|
||||||
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
|
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
|
||||||
import io.dropwizard.auth.basic.BasicCredentials;
|
import io.dropwizard.auth.basic.BasicCredentials;
|
||||||
import io.dropwizard.setup.Bootstrap;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Bootstrap;
|
||||||
|
import io.dropwizard.core.setup.Environment;
|
||||||
import io.grpc.ServerBuilder;
|
import io.grpc.ServerBuilder;
|
||||||
import io.grpc.ServerInterceptors;
|
import io.grpc.ServerInterceptors;
|
||||||
import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder;
|
import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder;
|
||||||
|
@ -50,6 +50,7 @@ import javax.servlet.DispatcherType;
|
||||||
import javax.servlet.FilterRegistration;
|
import javax.servlet.FilterRegistration;
|
||||||
import javax.servlet.ServletRegistration;
|
import javax.servlet.ServletRegistration;
|
||||||
import org.eclipse.jetty.servlets.CrossOriginFilter;
|
import org.eclipse.jetty.servlets.CrossOriginFilter;
|
||||||
|
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||||
import org.glassfish.jersey.server.ServerProperties;
|
import org.glassfish.jersey.server.ServerProperties;
|
||||||
import org.signal.event.AdminEventLogger;
|
import org.signal.event.AdminEventLogger;
|
||||||
import org.signal.event.GoogleCloudAdminEventLogger;
|
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.configuration.secrets.SecretsModule;
|
||||||
import org.whispersystems.textsecuregcm.controllers.AccountController;
|
import org.whispersystems.textsecuregcm.controllers.AccountController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.AccountControllerV2;
|
import org.whispersystems.textsecuregcm.controllers.AccountControllerV2;
|
||||||
|
import org.whispersystems.textsecuregcm.controllers.ArchiveController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.ArtController;
|
import org.whispersystems.textsecuregcm.controllers.ArtController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV2;
|
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV2;
|
||||||
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV3;
|
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV3;
|
||||||
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV4;
|
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV4;
|
||||||
import org.whispersystems.textsecuregcm.controllers.ArchiveController;
|
|
||||||
import org.whispersystems.textsecuregcm.controllers.CallLinkController;
|
import org.whispersystems.textsecuregcm.controllers.CallLinkController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.CertificateController;
|
import org.whispersystems.textsecuregcm.controllers.CertificateController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.ChallengeController;
|
import org.whispersystems.textsecuregcm.controllers.ChallengeController;
|
||||||
|
@ -706,7 +707,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
|
|
||||||
///
|
///
|
||||||
WebSocketEnvironment<AuthenticatedAccount> webSocketEnvironment = new WebSocketEnvironment<>(environment,
|
WebSocketEnvironment<AuthenticatedAccount> webSocketEnvironment = new WebSocketEnvironment<>(environment,
|
||||||
config.getWebSocketConfiguration(), 90000);
|
config.getWebSocketConfiguration(), Duration.ofMillis(90000));
|
||||||
webSocketEnvironment.setAuthenticator(new WebSocketAccountAuthenticator(accountAuthenticator));
|
webSocketEnvironment.setAuthenticator(new WebSocketAccountAuthenticator(accountAuthenticator));
|
||||||
webSocketEnvironment.setConnectListener(
|
webSocketEnvironment.setConnectListener(
|
||||||
new AuthenticatedConnectListener(receiptSender, messagesManager, pushNotificationManager,
|
new AuthenticatedConnectListener(receiptSender, messagesManager, pushNotificationManager,
|
||||||
|
@ -826,7 +827,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketEnvironment<AuthenticatedAccount> provisioningEnvironment = new WebSocketEnvironment<>(environment,
|
WebSocketEnvironment<AuthenticatedAccount> provisioningEnvironment = new WebSocketEnvironment<>(environment,
|
||||||
webSocketEnvironment.getRequestLog(), 60000);
|
webSocketEnvironment.getRequestLog(), Duration.ofMillis(60000));
|
||||||
provisioningEnvironment.jersey().register(new WebsocketRefreshApplicationEventListener(accountsManager, clientPresenceManager));
|
provisioningEnvironment.jersey().register(new WebsocketRefreshApplicationEventListener(accountsManager, clientPresenceManager));
|
||||||
provisioningEnvironment.setConnectListener(new ProvisioningConnectListener(provisioningManager));
|
provisioningEnvironment.setConnectListener(new ProvisioningConnectListener(provisioningManager));
|
||||||
provisioningEnvironment.jersey().register(new MetricsApplicationEventListener(TrafficSource.WEBSOCKET, clientReleaseManager));
|
provisioningEnvironment.jersey().register(new MetricsApplicationEventListener(TrafficSource.WEBSOCKET, clientReleaseManager));
|
||||||
|
@ -840,6 +841,8 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
webSocketEnvironment.jersey().property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
|
webSocketEnvironment.jersey().property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
|
||||||
provisioningEnvironment.jersey().property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
|
provisioningEnvironment.jersey().property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
|
||||||
|
|
||||||
|
JettyWebSocketServletContainerInitializer.configure(environment.getApplicationContext(), null);
|
||||||
|
|
||||||
WebSocketResourceProviderFactory<AuthenticatedAccount> webSocketServlet = new WebSocketResourceProviderFactory<>(
|
WebSocketResourceProviderFactory<AuthenticatedAccount> webSocketServlet = new WebSocketResourceProviderFactory<>(
|
||||||
webSocketEnvironment, AuthenticatedAccount.class, config.getWebSocketConfiguration());
|
webSocketEnvironment, AuthenticatedAccount.class, config.getWebSocketConfiguration());
|
||||||
WebSocketResourceProviderFactory<AuthenticatedAccount> provisioningServlet = new WebSocketResourceProviderFactory<>(
|
WebSocketResourceProviderFactory<AuthenticatedAccount> provisioningServlet = new WebSocketResourceProviderFactory<>(
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.configuration;
|
package org.whispersystems.textsecuregcm.configuration;
|
||||||
|
|
||||||
import io.dropwizard.util.Strings;
|
|
||||||
import io.dropwizard.validation.ValidationMethod;
|
import io.dropwizard.validation.ValidationMethod;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||||
|
|
||||||
public record GcpAttachmentsConfiguration(@NotBlank String domain,
|
public record GcpAttachmentsConfiguration(@NotBlank String domain,
|
||||||
|
@ -20,6 +20,6 @@ public record GcpAttachmentsConfiguration(@NotBlank String domain,
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ValidationMethod(message = "pathPrefix must be empty or start with /")
|
@ValidationMethod(message = "pathPrefix must be empty or start with /")
|
||||||
public boolean isPathPrefixValid() {
|
public boolean isPathPrefixValid() {
|
||||||
return Strings.isNullOrEmpty(pathPrefix) || pathPrefix.startsWith("/");
|
return StringUtils.isEmpty(pathPrefix) || pathPrefix.startsWith("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.gcp;
|
package org.whispersystems.textsecuregcm.gcp;
|
||||||
|
|
||||||
import io.dropwizard.util.Strings;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -16,6 +13,8 @@ import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
public class CanonicalRequestGenerator {
|
public class CanonicalRequestGenerator {
|
||||||
private static final DateTimeFormatter SIMPLE_UTC_DATE = DateTimeFormatter.ofPattern("yyyyMMdd", Locale.US).withZone(ZoneOffset.UTC);
|
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 result = new StringBuilder("POST\n");
|
||||||
|
|
||||||
final StringBuilder resourcePathBuilder = new StringBuilder();
|
final StringBuilder resourcePathBuilder = new StringBuilder();
|
||||||
if (!Strings.isNullOrEmpty(pathPrefix)) {
|
if (StringUtils.isNotEmpty(pathPrefix)) {
|
||||||
resourcePathBuilder.append(pathPrefix);
|
resourcePathBuilder.append(pathPrefix);
|
||||||
}
|
}
|
||||||
resourcePathBuilder.append('/').append(URLEncoder.encode(key, StandardCharsets.UTF_8));
|
resourcePathBuilder.append('/').append(URLEncoder.encode(key, StandardCharsets.UTF_8));
|
||||||
|
|
|
@ -17,10 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.databind.node.TextNode;
|
import com.fasterxml.jackson.databind.node.TextNode;
|
||||||
import io.dropwizard.logging.AbstractAppenderFactory;
|
import io.dropwizard.logging.common.AbstractAppenderFactory;
|
||||||
import io.dropwizard.logging.async.AsyncAppenderFactory;
|
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
|
||||||
import io.dropwizard.logging.filter.LevelFilterFactory;
|
import io.dropwizard.logging.common.filter.LevelFilterFactory;
|
||||||
import io.dropwizard.logging.layout.LayoutFactory;
|
import io.dropwizard.logging.common.layout.LayoutFactory;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
|
@ -7,7 +7,7 @@ package org.whispersystems.textsecuregcm.metrics;
|
||||||
|
|
||||||
import com.codahale.metrics.SharedMetricRegistries;
|
import com.codahale.metrics.SharedMetricRegistries;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
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.Meter;
|
||||||
import io.micrometer.core.instrument.MeterRegistry;
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import io.micrometer.core.instrument.Metrics;
|
import io.micrometer.core.instrument.Metrics;
|
||||||
|
|
|
@ -14,7 +14,7 @@ import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.ScheduledReporter;
|
import com.codahale.metrics.ScheduledReporter;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
import io.dropwizard.metrics.BaseReporterFactory;
|
import io.dropwizard.metrics.common.BaseReporterFactory;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.whispersystems.textsecuregcm.util.logging;
|
||||||
import ch.qos.logback.access.spi.IAccessEvent;
|
import ch.qos.logback.access.spi.IAccessEvent;
|
||||||
import ch.qos.logback.core.filter.Filter;
|
import ch.qos.logback.core.filter.Filter;
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
import io.dropwizard.logging.filter.FilterFactory;
|
import io.dropwizard.logging.common.filter.FilterFactory;
|
||||||
|
|
||||||
@JsonTypeName("requestLogEnabled")
|
@JsonTypeName("requestLogEnabled")
|
||||||
class RequestLogEnabledFilterFactory implements FilterFactory<IAccessEvent> {
|
class RequestLogEnabledFilterFactory implements FilterFactory<IAccessEvent> {
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.Cli;
|
import io.dropwizard.core.cli.Cli;
|
||||||
import io.dropwizard.cli.EnvironmentCommand;
|
import io.dropwizard.core.cli.EnvironmentCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
|
|
|
@ -8,9 +8,9 @@ package org.whispersystems.textsecuregcm.workers;
|
||||||
import static com.codahale.metrics.MetricRegistry.name;
|
import static com.codahale.metrics.MetricRegistry.name;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.EnvironmentCommand;
|
import io.dropwizard.core.cli.EnvironmentCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
import io.lettuce.core.resource.ClientResources;
|
import io.lettuce.core.resource.ClientResources;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
|
@ -7,6 +7,11 @@ package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.protobuf.ByteString;
|
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.impl.Arguments;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
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.signal.libsignal.protocol.ecc.ECPrivateKey;
|
||||||
import org.whispersystems.textsecuregcm.entities.MessageProtos;
|
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 {
|
public class CertificateCommand extends Command {
|
||||||
|
|
||||||
private static final Set<Integer> RESERVED_CERTIFICATE_IDS = Set.of(
|
private static final Set<Integer> RESERVED_CERTIFICATE_IDS = Set.of(
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import io.dropwizard.cli.Command;
|
import io.dropwizard.core.cli.Command;
|
||||||
import io.dropwizard.setup.Bootstrap;
|
import io.dropwizard.core.setup.Bootstrap;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.whispersystems.textsecuregcm.workers;
|
||||||
import static com.codahale.metrics.MetricRegistry.name;
|
import static com.codahale.metrics.MetricRegistry.name;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
import io.lettuce.core.resource.ClientResources;
|
import io.lettuce.core.resource.ClientResources;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.EnvironmentCommand;
|
import io.dropwizard.core.cli.EnvironmentCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.ServerCommand;
|
import io.dropwizard.core.cli.ServerCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
|
|
|
@ -7,9 +7,10 @@ package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import static com.codahale.metrics.MetricRegistry.name;
|
import static com.codahale.metrics.MetricRegistry.name;
|
||||||
|
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.ServerCommand;
|
import io.dropwizard.core.cli.ServerCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import io.dropwizard.cli.Command;
|
import io.dropwizard.core.cli.Command;
|
||||||
import io.dropwizard.setup.Bootstrap;
|
import io.dropwizard.core.setup.Bootstrap;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
import org.whispersystems.textsecuregcm.WhisperServerVersion;
|
import org.whispersystems.textsecuregcm.WhisperServerVersion;
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.EnvironmentCommand;
|
import io.dropwizard.core.cli.EnvironmentCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
package org.whispersystems.textsecuregcm.workers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import io.dropwizard.Application;
|
import io.dropwizard.core.Application;
|
||||||
import io.dropwizard.cli.EnvironmentCommand;
|
import io.dropwizard.core.cli.EnvironmentCommand;
|
||||||
import io.dropwizard.setup.Environment;
|
import io.dropwizard.core.setup.Environment;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
|
@ -5,15 +5,14 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.workers;
|
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.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
import org.signal.libsignal.zkgroup.ServerPublicParams;
|
import org.signal.libsignal.zkgroup.ServerPublicParams;
|
||||||
import org.signal.libsignal.zkgroup.ServerSecretParams;
|
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 class ZkParamsCommand extends Command {
|
||||||
|
|
||||||
public ZkParamsCommand() {
|
public ZkParamsCommand() {
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
||||||
import io.dropwizard.auth.Auth;
|
import io.dropwizard.auth.Auth;
|
||||||
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
|
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
|
||||||
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
|
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
|
||||||
|
@ -28,9 +27,11 @@ import io.dropwizard.jersey.DropwizardResourceConfig;
|
||||||
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
||||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||||
import io.dropwizard.testing.junit5.ResourceExtension;
|
import io.dropwizard.testing.junit5.ResourceExtension;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
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.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
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.ApplicationHandler;
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
|
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
|
||||||
|
@ -337,7 +339,7 @@ class AuthEnablementRefreshRequirementProviderTest {
|
||||||
|
|
||||||
provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
||||||
requestLog, new TestPrincipal("test", account, authenticatedDevice), new ProtobufWebSocketMessageFactory(),
|
requestLog, new TestPrincipal("test", account, authenticatedDevice), new ProtobufWebSocketMessageFactory(),
|
||||||
Optional.empty(), 30000);
|
Optional.empty(), Duration.ofMillis(30000));
|
||||||
|
|
||||||
remoteEndpoint = mock(RemoteEndpoint.class);
|
remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
|
@ -363,9 +365,9 @@ class AuthEnablementRefreshRequirementProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private SubProtocol.WebSocketResponseMessage verifyAndGetResponse(final RemoteEndpoint remoteEndpoint)
|
private SubProtocol.WebSocketResponseMessage verifyAndGetResponse(final RemoteEndpoint remoteEndpoint)
|
||||||
throws InvalidProtocolBufferException {
|
throws IOException {
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> 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();
|
return SubProtocol.WebSocketMessage.parseFrom(responseBytesCaptor.getValue().array()).getResponse();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,10 @@ import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
||||||
import io.micrometer.core.instrument.Counter;
|
import io.micrometer.core.instrument.Counter;
|
||||||
import io.micrometer.core.instrument.MeterRegistry;
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import io.micrometer.core.instrument.Tag;
|
import io.micrometer.core.instrument.Tag;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
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.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
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.ApplicationHandler;
|
||||||
import org.glassfish.jersey.server.ContainerRequest;
|
import org.glassfish.jersey.server.ContainerRequest;
|
||||||
import org.glassfish.jersey.server.ContainerResponse;
|
import org.glassfish.jersey.server.ContainerResponse;
|
||||||
|
@ -121,7 +124,7 @@ class MetricsRequestEventListenerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageSuccess() throws InvalidProtocolBufferException {
|
void testActualRouteMessageSuccess() throws IOException {
|
||||||
final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class);
|
final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class);
|
||||||
when(applicationEventListener.onRequest(any())).thenReturn(listener);
|
when(applicationEventListener.onRequest(any())).thenReturn(listener);
|
||||||
|
|
||||||
|
@ -140,7 +143,7 @@ class MetricsRequestEventListenerTest {
|
||||||
new TestPrincipal("foo"),
|
new TestPrincipal("foo"),
|
||||||
new ProtobufWebSocketMessageFactory(),
|
new ProtobufWebSocketMessageFactory(),
|
||||||
Optional.empty(),
|
Optional.empty(),
|
||||||
30000);
|
Duration.ofMillis(30000));
|
||||||
|
|
||||||
final Session session = mock(Session.class);
|
final Session session = mock(Session.class);
|
||||||
final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -163,7 +166,7 @@ class MetricsRequestEventListenerTest {
|
||||||
provider.onWebSocketBinary(message, 0, message.length);
|
provider.onWebSocketBinary(message, 0, message.length);
|
||||||
|
|
||||||
final ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
final ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -187,7 +190,7 @@ class MetricsRequestEventListenerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageSuccessNoUserAgent() throws InvalidProtocolBufferException {
|
void testActualRouteMessageSuccessNoUserAgent() throws IOException {
|
||||||
final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class);
|
final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class);
|
||||||
when(applicationEventListener.onRequest(any())).thenReturn(listener);
|
when(applicationEventListener.onRequest(any())).thenReturn(listener);
|
||||||
|
|
||||||
|
@ -200,8 +203,10 @@ class MetricsRequestEventListenerTest {
|
||||||
|
|
||||||
final ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
final ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
final WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
final WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
final WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
final WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1",
|
||||||
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
|
applicationHandler,
|
||||||
|
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
|
||||||
|
Duration.ofMillis(30000));
|
||||||
|
|
||||||
final Session session = mock(Session.class);
|
final Session session = mock(Session.class);
|
||||||
final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -222,7 +227,7 @@ class MetricsRequestEventListenerTest {
|
||||||
provider.onWebSocketBinary(message, 0, message.length);
|
provider.onWebSocketBinary(message, 0, message.length);
|
||||||
|
|
||||||
final ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
final ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ class AccountsManagerTest {
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
asyncCommands = mock(RedisAdvancedClusterAsyncCommands.class);
|
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.get(any())).thenReturn(MockRedisFuture.completedFuture(null));
|
||||||
when(asyncCommands.setex(any(), anyLong(), any())).thenReturn(MockRedisFuture.completedFuture("OK"));
|
when(asyncCommands.setex(any(), anyLong(), any())).thenReturn(MockRedisFuture.completedFuture("OK"));
|
||||||
|
|
||||||
|
|
|
@ -679,7 +679,7 @@ class MessagesCacheTest {
|
||||||
pages.add(generatePage());
|
pages.add(generatePage());
|
||||||
pages.add(generateStaleEphemeralPage());
|
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()))
|
.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));
|
final AsyncCommand<?, ?, ?> removeSuccess = new AsyncCommand<>(mock(RedisCommand.class));
|
||||||
removeSuccess.complete();
|
removeSuccess.complete();
|
||||||
|
|
||||||
when(asyncCommands.evalsha(any(), any(), any(), any()))
|
when(asyncCommands.evalsha(any(), any(), any(byte[][].class), any(byte[][].class)))
|
||||||
.thenReturn((RedisFuture) removeSuccess);
|
.thenReturn((RedisFuture) removeSuccess);
|
||||||
|
|
||||||
final Publisher<?> allMessages = messagesCache.get(UUID.randomUUID(), Device.PRIMARY_ID);
|
final Publisher<?> allMessages = messagesCache.get(UUID.randomUUID(), Device.PRIMARY_ID);
|
||||||
|
@ -696,9 +696,9 @@ class MessagesCacheTest {
|
||||||
StepVerifier.setDefaultTimeout(Duration.ofSeconds(5));
|
StepVerifier.setDefaultTimeout(Duration.ofSeconds(5));
|
||||||
|
|
||||||
// async commands are used for remove(), and nothing should happen until we are subscribed
|
// 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)
|
// 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)
|
StepVerifier.create(allMessages)
|
||||||
.expectSubscription()
|
.expectSubscription()
|
||||||
|
@ -708,7 +708,7 @@ class MessagesCacheTest {
|
||||||
.verify();
|
.verify();
|
||||||
|
|
||||||
assertTrue(pages.isEmpty());
|
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<byte[]> generatePage() {
|
private List<byte[]> generatePage() {
|
||||||
|
|
|
@ -5,12 +5,11 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.tests.util;
|
package org.whispersystems.textsecuregcm.tests.util;
|
||||||
|
|
||||||
import static io.dropwizard.testing.FixtureHelpers.fixture;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import io.dropwizard.util.Resources;
|
||||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||||
|
|
||||||
public class JsonHelpers {
|
public class JsonHelpers {
|
||||||
|
@ -26,6 +25,7 @@ public class JsonHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String jsonFixture(String filename) throws IOException {
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,24 +50,6 @@ public class RedisClusterHelper {
|
||||||
return null;
|
return null;
|
||||||
}).when(cluster).useCluster(any(Consumer.class));
|
}).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 -> {
|
when(cluster.withBinaryCluster(any(Function.class))).thenAnswer(invocation -> {
|
||||||
return invocation.getArgument(0, Function.class).apply(binaryConnection);
|
return invocation.getArgument(0, Function.class).apply(binaryConnection);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.util.logging;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.matches;
|
import static org.mockito.ArgumentMatchers.matches;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
@ -20,8 +21,10 @@ import io.dropwizard.jersey.DropwizardResourceConfig;
|
||||||
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
||||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||||
import io.dropwizard.testing.junit5.ResourceExtension;
|
import io.dropwizard.testing.junit5.ResourceExtension;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
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.ApplicationHandler;
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
import org.glassfish.jersey.server.ServerProperties;
|
import org.glassfish.jersey.server.ServerProperties;
|
||||||
|
@ -159,7 +163,7 @@ class LoggingUnhandledExceptionMapperTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebSocketResourceProvider<TestPrincipal> createWebsocketProvider(final String userAgentHeader,
|
private WebSocketResourceProvider<TestPrincipal> createWebsocketProvider(final String userAgentHeader,
|
||||||
final Session session, final Consumer<ByteBuffer> responseHandler) {
|
final Session session, final Consumer<ByteBuffer> responseHandler) throws IOException {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(exceptionMapper);
|
resourceConfig.register(exceptionMapper);
|
||||||
resourceConfig.register(new TestController());
|
resourceConfig.register(new TestController());
|
||||||
|
@ -170,14 +174,14 @@ class LoggingUnhandledExceptionMapperTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
when(remoteEndpoint.sendBytesByFuture(any()))
|
doAnswer(answer -> {
|
||||||
.thenAnswer(answer -> {
|
responseHandler.accept(answer.getArgument(0, ByteBuffer.class));
|
||||||
responseHandler.accept(answer.getArgument(0, ByteBuffer.class));
|
return null;
|
||||||
return CompletableFuture.completedFuture(null);
|
}).when(remoteEndpoint).sendBytes(any(), any(WriteCallback.class));
|
||||||
});
|
|
||||||
UpgradeRequest request = mock(UpgradeRequest.class);
|
UpgradeRequest request = mock(UpgradeRequest.class);
|
||||||
|
|
||||||
when(session.getUpgradeRequest()).thenReturn(request);
|
when(session.getUpgradeRequest()).thenReturn(request);
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
mock-maker-inline
|
|
|
@ -13,12 +13,11 @@
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
<artifactId>websocket-api</artifactId>
|
<artifactId>websocket-jetty-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
<artifactId>websocket-server</artifactId>
|
<artifactId>websocket-jetty-server</artifactId>
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
|
@ -97,11 +96,6 @@
|
||||||
<artifactId>jsr305</artifactId>
|
<artifactId>jsr305</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-inline</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter</artifactId>
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
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.eclipse.jetty.websocket.api.WriteCallback;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -99,7 +99,7 @@ public class WebSocketClient {
|
||||||
public void hardDisconnectQuietly() {
|
public void hardDisconnectQuietly() {
|
||||||
try {
|
try {
|
||||||
session.disconnect();
|
session.disconnect();
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
// quietly we said
|
// quietly we said
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,28 @@ package org.whispersystems.websocket;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
import com.google.protobuf.UninitializedMessageException;
|
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.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketListener;
|
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.internal.MapPropertiesDelegate;
|
||||||
import org.glassfish.jersey.server.ApplicationHandler;
|
import org.glassfish.jersey.server.ApplicationHandler;
|
||||||
import org.glassfish.jersey.server.ContainerRequest;
|
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.session.WebSocketSessionContext;
|
||||||
import org.whispersystems.websocket.setup.WebSocketConnectListener;
|
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")
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
public class WebSocketResourceProvider<T extends Principal> implements WebSocketListener {
|
public class WebSocketResourceProvider<T extends Principal> implements WebSocketListener {
|
||||||
|
@ -57,44 +58,44 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
|
||||||
|
|
||||||
private final Map<Long, CompletableFuture<WebSocketResponseMessage>> requestMap = new ConcurrentHashMap<>();
|
private final Map<Long, CompletableFuture<WebSocketResponseMessage>> requestMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final T authenticated;
|
private final T authenticated;
|
||||||
private final WebSocketMessageFactory messageFactory;
|
private final WebSocketMessageFactory messageFactory;
|
||||||
private final Optional<WebSocketConnectListener> connectListener;
|
private final Optional<WebSocketConnectListener> connectListener;
|
||||||
private final ApplicationHandler jerseyHandler;
|
private final ApplicationHandler jerseyHandler;
|
||||||
private final WebsocketRequestLog requestLog;
|
private final WebsocketRequestLog requestLog;
|
||||||
private final long idleTimeoutMillis;
|
private final Duration idleTimeout;
|
||||||
private final String remoteAddress;
|
private final String remoteAddress;
|
||||||
|
|
||||||
private Session session;
|
private Session session;
|
||||||
private RemoteEndpoint remoteEndpoint;
|
private RemoteEndpoint remoteEndpoint;
|
||||||
private WebSocketSessionContext context;
|
private WebSocketSessionContext context;
|
||||||
|
|
||||||
private static final Set<String> EXCLUDED_UPGRADE_REQUEST_HEADERS = Set.of("connection", "upgrade");
|
private static final Set<String> EXCLUDED_UPGRADE_REQUEST_HEADERS = Set.of("connection", "upgrade");
|
||||||
|
|
||||||
public WebSocketResourceProvider(String remoteAddress,
|
public WebSocketResourceProvider(String remoteAddress,
|
||||||
ApplicationHandler jerseyHandler,
|
ApplicationHandler jerseyHandler,
|
||||||
WebsocketRequestLog requestLog,
|
WebsocketRequestLog requestLog,
|
||||||
T authenticated,
|
T authenticated,
|
||||||
WebSocketMessageFactory messageFactory,
|
WebSocketMessageFactory messageFactory,
|
||||||
Optional<WebSocketConnectListener> connectListener,
|
Optional<WebSocketConnectListener> connectListener,
|
||||||
long idleTimeoutMillis)
|
Duration idleTimeout) {
|
||||||
{
|
this.remoteAddress = remoteAddress;
|
||||||
this.remoteAddress = remoteAddress;
|
this.jerseyHandler = jerseyHandler;
|
||||||
this.jerseyHandler = jerseyHandler;
|
this.requestLog = requestLog;
|
||||||
this.requestLog = requestLog;
|
this.authenticated = authenticated;
|
||||||
this.authenticated = authenticated;
|
this.messageFactory = messageFactory;
|
||||||
this.messageFactory = messageFactory;
|
this.connectListener = connectListener;
|
||||||
this.connectListener = connectListener;
|
this.idleTimeout = idleTimeout;
|
||||||
this.idleTimeoutMillis = idleTimeoutMillis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWebSocketConnect(Session session) {
|
public void onWebSocketConnect(Session session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.remoteEndpoint = session.getRemote();
|
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.context.setAuthenticated(authenticated);
|
||||||
this.session.setIdleTimeout(idleTimeoutMillis);
|
this.session.setIdleTimeout(idleTimeout);
|
||||||
|
|
||||||
connectListener.ifPresent(listener -> listener.onWebSocketConnect(this.context));
|
connectListener.ifPresent(listener -> listener.onWebSocketConnect(this.context));
|
||||||
}
|
}
|
||||||
|
@ -129,12 +130,12 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
|
||||||
handleResponse(webSocketMessage.getResponseMessage());
|
handleResponse(webSocketMessage.getResponseMessage());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
close(session, 1018, "Badly formatted");
|
close(session, 1007, "Badly formatted");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (UninitializedMessageException | InvalidMessageException e) {
|
} catch (UninitializedMessageException | InvalidMessageException e) {
|
||||||
logger.debug("Parsing", e);
|
logger.debug("Parsing", e);
|
||||||
close(session, 1018, "Badly formatted");
|
close(session, 1007, "Badly formatted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,23 +160,36 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRequest(WebSocketRequestMessage requestMessage) {
|
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()));
|
containerRequest.headers(getCombinedHeaders(session.getUpgradeRequest().getHeaders(), requestMessage.getHeaders()));
|
||||||
|
|
||||||
if (requestMessage.getBody().isPresent()) {
|
if (requestMessage.getBody().isPresent()) {
|
||||||
containerRequest.setEntityStream(new ByteArrayInputStream(requestMessage.getBody().get()));
|
containerRequest.setEntityStream(new ByteArrayInputStream(requestMessage.getBody().get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
|
ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
|
||||||
CompletableFuture<ContainerResponse> responseFuture = (CompletableFuture<ContainerResponse>) jerseyHandler.apply(containerRequest, responseBody);
|
CompletableFuture<ContainerResponse> responseFuture = (CompletableFuture<ContainerResponse>) jerseyHandler.apply(
|
||||||
|
containerRequest, responseBody);
|
||||||
|
|
||||||
responseFuture.thenAccept(response -> {
|
responseFuture.thenAccept(response -> {
|
||||||
sendResponse(requestMessage, response, responseBody);
|
try {
|
||||||
|
sendResponse(requestMessage, response, responseBody);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
requestLog.log(remoteAddress, containerRequest, response);
|
requestLog.log(remoteAddress, containerRequest, response);
|
||||||
}).exceptionally(exception -> {
|
}).exceptionally(exception -> {
|
||||||
logger.warn("Websocket Error: " + requestMessage.getVerb() + " " + requestMessage.getPath() + "\n" + requestMessage.getBody(), exception);
|
logger.warn("Websocket Error: " + requestMessage.getVerb() + " " + requestMessage.getPath() + "\n"
|
||||||
sendErrorResponse(requestMessage, Response.status(500).build());
|
+ requestMessage.getBody(), exception);
|
||||||
requestLog.log(remoteAddress, containerRequest, new ContainerResponse(containerRequest, Response.status(500).build()));
|
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;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -217,7 +231,8 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
|
||||||
session.close(status, message);
|
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()) {
|
if (requestMessage.hasRequestId()) {
|
||||||
byte[] body = responseBody.toByteArray();
|
byte[] body = responseBody.toByteArray();
|
||||||
|
|
||||||
|
@ -226,25 +241,25 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] responseBytes = messageFactory.createResponse(requestMessage.getRequestId(),
|
byte[] responseBytes = messageFactory.createResponse(requestMessage.getRequestId(),
|
||||||
response.getStatus(),
|
response.getStatus(),
|
||||||
response.getStatusInfo().getReasonPhrase(),
|
response.getStatusInfo().getReasonPhrase(),
|
||||||
getHeaderList(response.getStringHeaders()),
|
getHeaderList(response.getStringHeaders()),
|
||||||
Optional.ofNullable(body))
|
Optional.ofNullable(body))
|
||||||
.toByteArray();
|
.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()) {
|
if (requestMessage.hasRequestId()) {
|
||||||
WebSocketMessage response = messageFactory.createResponse(requestMessage.getRequestId(),
|
WebSocketMessage response = messageFactory.createResponse(requestMessage.getRequestId(),
|
||||||
error.getStatus(),
|
error.getStatus(),
|
||||||
"Error response",
|
"Error response",
|
||||||
getHeaderList(error.getStringHeaders()),
|
getHeaderList(error.getStringHeaders()),
|
||||||
Optional.empty());
|
Optional.empty());
|
||||||
|
|
||||||
remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(response.toByteArray()));
|
remoteEndpoint.sendBytes(ByteBuffer.wrap(response.toByteArray()), WriteCallback.NOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,15 @@ import static java.util.Optional.ofNullable;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
import org.eclipse.jetty.websocket.server.JettyWebSocketCreator;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
import org.eclipse.jetty.websocket.server.JettyWebSocketServlet;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
|
||||||
import org.glassfish.jersey.server.ApplicationHandler;
|
import org.glassfish.jersey.server.ApplicationHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -28,7 +29,8 @@ import org.whispersystems.websocket.configuration.WebSocketConfiguration;
|
||||||
import org.whispersystems.websocket.session.WebSocketSessionContextValueFactoryProvider;
|
import org.whispersystems.websocket.session.WebSocketSessionContextValueFactoryProvider;
|
||||||
import org.whispersystems.websocket.setup.WebSocketEnvironment;
|
import org.whispersystems.websocket.setup.WebSocketEnvironment;
|
||||||
|
|
||||||
public class WebSocketResourceProviderFactory<T extends Principal> extends WebSocketServlet implements WebSocketCreator {
|
public class WebSocketResourceProviderFactory<T extends Principal> extends JettyWebSocketServlet implements
|
||||||
|
JettyWebSocketCreator {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(WebSocketResourceProviderFactory.class);
|
private static final Logger logger = LoggerFactory.getLogger(WebSocketResourceProviderFactory.class);
|
||||||
|
|
||||||
|
@ -50,10 +52,10 @@ public class WebSocketResourceProviderFactory<T extends Principal> extends WebSo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
|
public Object createWebSocket(final JettyServerUpgradeRequest request, final JettyServerUpgradeResponse response) {
|
||||||
try {
|
try {
|
||||||
Optional<WebSocketAuthenticator<T>> authenticator = Optional.ofNullable(environment.getAuthenticator());
|
Optional<WebSocketAuthenticator<T>> authenticator = Optional.ofNullable(environment.getAuthenticator());
|
||||||
T authenticated = null;
|
T authenticated = null;
|
||||||
|
|
||||||
if (authenticator.isPresent()) {
|
if (authenticator.isPresent()) {
|
||||||
AuthenticationResult<T> authenticationResult = authenticator.get().authenticate(request);
|
AuthenticationResult<T> authenticationResult = authenticator.get().authenticate(request);
|
||||||
|
@ -72,7 +74,7 @@ public class WebSocketResourceProviderFactory<T extends Principal> extends WebSo
|
||||||
authenticated,
|
authenticated,
|
||||||
this.environment.getMessageFactory(),
|
this.environment.getMessageFactory(),
|
||||||
ofNullable(this.environment.getConnectListener()),
|
ofNullable(this.environment.getConnectListener()),
|
||||||
this.environment.getIdleTimeoutMillis());
|
this.environment.getIdleTimeout());
|
||||||
} catch (AuthenticationException | IOException e) {
|
} catch (AuthenticationException | IOException e) {
|
||||||
logger.warn("Authentication failure", e);
|
logger.warn("Authentication failure", e);
|
||||||
try {
|
try {
|
||||||
|
@ -84,20 +86,23 @@ public class WebSocketResourceProviderFactory<T extends Principal> extends WebSo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(WebSocketServletFactory factory) {
|
public void configure(JettyWebSocketServletFactory factory) {
|
||||||
factory.setCreator(this);
|
factory.setCreator(this);
|
||||||
factory.getPolicy().setMaxBinaryMessageSize(configuration.getMaxBinaryMessageSize());
|
factory.setMaxBinaryMessageSize(configuration.getMaxBinaryMessageSize());
|
||||||
factory.getPolicy().setMaxTextMessageSize(configuration.getMaxTextMessageSize());
|
factory.setMaxTextMessageSize(configuration.getMaxTextMessageSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRemoteAddress(ServletUpgradeRequest request) {
|
private String getRemoteAddress(JettyServerUpgradeRequest request) {
|
||||||
String forwardedFor = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
|
String forwardedFor = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
|
||||||
|
|
||||||
if (forwardedFor == null || forwardedFor.isBlank()) {
|
if (forwardedFor == null || forwardedFor.isBlank()) {
|
||||||
return request.getRemoteAddress();
|
if (request.getRemoteSocketAddress() instanceof InetSocketAddress inetSocketAddress) {
|
||||||
|
return inetSocketAddress.getAddress().getHostAddress();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return Arrays.stream(forwardedFor.split(","))
|
return Arrays.stream(forwardedFor.split(","))
|
||||||
.map(String::trim)
|
.map(String::trim)
|
||||||
.reduce((a, b) -> b)
|
.reduce((a, b) -> b)
|
||||||
.orElseThrow();
|
.orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Optional;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||||
|
|
||||||
public interface WebSocketAuthenticator<T extends Principal> {
|
public interface WebSocketAuthenticator<T extends Principal> {
|
||||||
|
|
||||||
AuthenticationResult<T> authenticate(UpgradeRequest request) throws AuthenticationException;
|
AuthenticationResult<T> authenticate(UpgradeRequest request) throws AuthenticationException;
|
||||||
|
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
package org.whispersystems.websocket.logging;
|
package org.whispersystems.websocket.logging;
|
||||||
|
|
||||||
import ch.qos.logback.core.AsyncAppenderBase;
|
import ch.qos.logback.core.AsyncAppenderBase;
|
||||||
import io.dropwizard.logging.async.AsyncAppenderFactory;
|
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
|
||||||
|
|
||||||
public class AsyncWebsocketEventAppenderFactory implements AsyncAppenderFactory<WebsocketEvent> {
|
public class AsyncWebsocketEventAppenderFactory implements AsyncAppenderFactory<WebsocketEvent> {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,12 +15,12 @@ import java.util.List;
|
||||||
|
|
||||||
import ch.qos.logback.classic.Logger;
|
import ch.qos.logback.classic.Logger;
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import io.dropwizard.logging.AppenderFactory;
|
import io.dropwizard.logging.common.AppenderFactory;
|
||||||
import io.dropwizard.logging.ConsoleAppenderFactory;
|
import io.dropwizard.logging.common.ConsoleAppenderFactory;
|
||||||
import io.dropwizard.logging.async.AsyncAppenderFactory;
|
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
|
||||||
import io.dropwizard.logging.filter.LevelFilterFactory;
|
import io.dropwizard.logging.common.filter.LevelFilterFactory;
|
||||||
import io.dropwizard.logging.filter.NullLevelFilterFactory;
|
import io.dropwizard.logging.common.filter.NullLevelFilterFactory;
|
||||||
import io.dropwizard.logging.layout.LayoutFactory;
|
import io.dropwizard.logging.common.layout.LayoutFactory;
|
||||||
|
|
||||||
public class WebsocketRequestLoggerFactory {
|
public class WebsocketRequestLoggerFactory {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ package org.whispersystems.websocket.logging.layout;
|
||||||
|
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import ch.qos.logback.core.pattern.PatternLayoutBase;
|
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 org.whispersystems.websocket.logging.WebsocketEvent;
|
||||||
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
|
@ -6,10 +6,10 @@ package org.whispersystems.websocket.logging.layout.converters;
|
||||||
|
|
||||||
import ch.qos.logback.core.CoreConstants;
|
import ch.qos.logback.core.CoreConstants;
|
||||||
import ch.qos.logback.core.util.CachingDateFormatter;
|
import ch.qos.logback.core.util.CachingDateFormatter;
|
||||||
import org.whispersystems.websocket.logging.WebsocketEvent;
|
import java.time.ZoneId;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.Optional;
|
||||||
|
import org.whispersystems.websocket.logging.WebsocketEvent;
|
||||||
|
|
||||||
public class DateConverter extends WebSocketEventConverter {
|
public class DateConverter extends WebSocketEventConverter {
|
||||||
|
|
||||||
|
@ -28,7 +28,15 @@ public class DateConverter extends WebSocketEventConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cachingDateFormatter = new CachingDateFormatter(datePattern);
|
List<String> optionList = getOptionList();
|
||||||
|
|
||||||
|
Optional<ZoneId> 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);
|
// maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
addWarn("Could not instantiate SimpleDateFormat with pattern " + datePattern, 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);
|
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
|
@Override
|
||||||
|
|
|
@ -6,7 +6,8 @@ package org.whispersystems.websocket.setup;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.dropwizard.jersey.DropwizardResourceConfig;
|
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.glassfish.jersey.server.ResourceConfig;
|
||||||
import org.whispersystems.websocket.auth.WebSocketAuthenticator;
|
import org.whispersystems.websocket.auth.WebSocketAuthenticator;
|
||||||
import org.whispersystems.websocket.configuration.WebSocketConfiguration;
|
import org.whispersystems.websocket.configuration.WebSocketConfiguration;
|
||||||
|
@ -19,31 +20,31 @@ import java.security.Principal;
|
||||||
|
|
||||||
public class WebSocketEnvironment<T extends Principal> {
|
public class WebSocketEnvironment<T extends Principal> {
|
||||||
|
|
||||||
private final ResourceConfig jerseyConfig;
|
private final ResourceConfig jerseyConfig;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final Validator validator;
|
private final Validator validator;
|
||||||
private final WebsocketRequestLog requestLog;
|
private final WebsocketRequestLog requestLog;
|
||||||
private final long idleTimeoutMillis;
|
private final Duration idleTimeout;
|
||||||
|
|
||||||
private WebSocketAuthenticator<T> authenticator;
|
private WebSocketAuthenticator<T> authenticator;
|
||||||
private WebSocketMessageFactory messageFactory;
|
private WebSocketMessageFactory messageFactory;
|
||||||
private WebSocketConnectListener connectListener;
|
private WebSocketConnectListener connectListener;
|
||||||
|
|
||||||
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration) {
|
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration) {
|
||||||
this(environment, configuration, 60000);
|
this(environment, configuration, Duration.ofMillis(60000));
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration, long idleTimeoutMillis) {
|
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration, Duration idleTimeout) {
|
||||||
this(environment, configuration.getRequestLog().build("websocket"), idleTimeoutMillis);
|
this(environment, configuration.getRequestLog().build("websocket"), idleTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketEnvironment(Environment environment, WebsocketRequestLog requestLog, long idleTimeoutMillis) {
|
public WebSocketEnvironment(Environment environment, WebsocketRequestLog requestLog, Duration idleTimeout) {
|
||||||
this.jerseyConfig = new DropwizardResourceConfig(environment.metrics());
|
this.jerseyConfig = new DropwizardResourceConfig(environment.metrics());
|
||||||
this.objectMapper = environment.getObjectMapper();
|
this.objectMapper = environment.getObjectMapper();
|
||||||
this.validator = environment.getValidator();
|
this.validator = environment.getValidator();
|
||||||
this.requestLog = requestLog;
|
this.requestLog = requestLog;
|
||||||
this.messageFactory = new ProtobufWebSocketMessageFactory();
|
this.messageFactory = new ProtobufWebSocketMessageFactory();
|
||||||
this.idleTimeoutMillis = idleTimeoutMillis;
|
this.idleTimeout = idleTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceConfig jersey() {
|
public ResourceConfig jersey() {
|
||||||
|
@ -58,8 +59,8 @@ public class WebSocketEnvironment<T extends Principal> {
|
||||||
this.authenticator = authenticator;
|
this.authenticator = authenticator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getIdleTimeoutMillis() {
|
public Duration getIdleTimeout() {
|
||||||
return idleTimeoutMillis;
|
return idleTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectMapper getObjectMapper() {
|
public ObjectMapper getObjectMapper() {
|
||||||
|
|
|
@ -20,10 +20,9 @@ import java.util.Optional;
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse;
|
||||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -37,8 +36,8 @@ public class WebSocketResourceProviderFactoryTest {
|
||||||
private ResourceConfig jerseyEnvironment;
|
private ResourceConfig jerseyEnvironment;
|
||||||
private WebSocketEnvironment<Account> environment;
|
private WebSocketEnvironment<Account> environment;
|
||||||
private WebSocketAuthenticator<Account> authenticator;
|
private WebSocketAuthenticator<Account> authenticator;
|
||||||
private ServletUpgradeRequest request;
|
private JettyServerUpgradeRequest request;
|
||||||
private ServletUpgradeResponse response;
|
private JettyServerUpgradeResponse response;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
|
@ -47,8 +46,8 @@ public class WebSocketResourceProviderFactoryTest {
|
||||||
environment = mock(WebSocketEnvironment.class);
|
environment = mock(WebSocketEnvironment.class);
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
authenticator = mock(WebSocketAuthenticator.class);
|
authenticator = mock(WebSocketAuthenticator.class);
|
||||||
request = mock(ServletUpgradeRequest.class);
|
request = mock(JettyServerUpgradeRequest.class);
|
||||||
response = mock(ServletUpgradeResponse.class);
|
response = mock(JettyServerUpgradeResponse.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,9 +110,8 @@ public class WebSocketResourceProviderFactoryTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testConfigure() {
|
void testConfigure() {
|
||||||
WebSocketServletFactory servletFactory = mock(WebSocketServletFactory.class);
|
JettyWebSocketServletFactory servletFactory = mock(JettyWebSocketServletFactory.class);
|
||||||
when(environment.jersey()).thenReturn(jerseyEnvironment);
|
when(environment.jersey()).thenReturn(jerseyEnvironment);
|
||||||
when(servletFactory.getPolicy()).thenReturn(mock(WebSocketPolicy.class));
|
|
||||||
|
|
||||||
WebSocketResourceProviderFactory<Account> factory = new WebSocketResourceProviderFactory<>(environment,
|
WebSocketResourceProviderFactory<Account> factory = new WebSocketResourceProviderFactory<>(environment,
|
||||||
Account.class,
|
Account.class,
|
||||||
|
|
|
@ -11,21 +11,21 @@ import static org.mockito.Mockito.anyString;
|
||||||
import static org.mockito.Mockito.eq;
|
import static org.mockito.Mockito.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
||||||
import io.dropwizard.auth.Auth;
|
import io.dropwizard.auth.Auth;
|
||||||
import io.dropwizard.jersey.DropwizardResourceConfig;
|
import io.dropwizard.jersey.DropwizardResourceConfig;
|
||||||
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -80,7 +80,7 @@ class WebSocketResourceProviderTest {
|
||||||
new TestPrincipal("fooz"),
|
new TestPrincipal("fooz"),
|
||||||
new ProtobufWebSocketMessageFactory(),
|
new ProtobufWebSocketMessageFactory(),
|
||||||
Optional.of(connectListener),
|
Optional.of(connectListener),
|
||||||
30000);
|
Duration.ofMillis(30000));
|
||||||
|
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
UpgradeRequest request = mock(UpgradeRequest.class);
|
UpgradeRequest request = mock(UpgradeRequest.class);
|
||||||
|
@ -105,7 +105,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = mock(ApplicationHandler.class);
|
ApplicationHandler applicationHandler = mock(ApplicationHandler.class);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -164,7 +165,7 @@ class WebSocketResourceProviderTest {
|
||||||
assertThat(bundledRequest.getPath(false)).isEqualTo("bar");
|
assertThat(bundledRequest.getPath(false)).isEqualTo("bar");
|
||||||
|
|
||||||
verify(requestLog).log(eq("127.0.0.1"), eq(bundledRequest), eq(response));
|
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(
|
SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom(
|
||||||
responseCaptor.getValue().array());
|
responseCaptor.getValue().array());
|
||||||
|
@ -180,7 +181,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = mock(ApplicationHandler.class);
|
ApplicationHandler applicationHandler = mock(ApplicationHandler.class);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -215,7 +217,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom(
|
SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom(
|
||||||
responseCaptor.getValue().array());
|
responseCaptor.getValue().array());
|
||||||
|
@ -225,7 +227,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageSuccess() throws InvalidProtocolBufferException {
|
void testActualRouteMessageSuccess() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -235,7 +237,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -253,7 +256,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -264,7 +267,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageNotFound() throws InvalidProtocolBufferException {
|
void testActualRouteMessageNotFound() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -274,7 +277,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -292,7 +296,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -303,7 +307,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageAuthorized() throws InvalidProtocolBufferException {
|
void testActualRouteMessageAuthorized() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -314,7 +318,7 @@ class WebSocketResourceProviderTest {
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
||||||
requestLog, new TestPrincipal("authorizedUserName"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
|
requestLog, new TestPrincipal("authorizedUserName"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
|
||||||
30000);
|
Duration.ofMillis(30000));
|
||||||
|
|
||||||
Session session = mock(Session.class);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -332,7 +336,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -343,7 +347,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageUnauthorized() throws InvalidProtocolBufferException {
|
void testActualRouteMessageUnauthorized() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -353,7 +357,7 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -371,7 +375,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -381,7 +385,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageOptionalAuthorizedPresent() throws InvalidProtocolBufferException {
|
void testActualRouteMessageOptionalAuthorizedPresent() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -391,7 +395,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -409,7 +414,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -420,7 +425,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageOptionalAuthorizedEmpty() throws InvalidProtocolBufferException {
|
void testActualRouteMessageOptionalAuthorizedEmpty() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -430,7 +435,7 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -448,7 +453,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -459,7 +464,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessagePutAuthenticatedEntity() throws InvalidProtocolBufferException, JsonProcessingException {
|
void testActualRouteMessagePutAuthenticatedEntity() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -469,7 +474,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -488,7 +494,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -499,8 +505,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessagePutAuthenticatedBadEntity()
|
void testActualRouteMessagePutAuthenticatedBadEntity() throws Exception {
|
||||||
throws InvalidProtocolBufferException, JsonProcessingException {
|
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
|
||||||
|
@ -510,7 +515,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -529,7 +535,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -540,7 +546,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteMessageExceptionMapping() throws InvalidProtocolBufferException {
|
void testActualRouteMessageExceptionMapping() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new TestExceptionMapper());
|
resourceConfig.register(new TestExceptionMapper());
|
||||||
|
@ -551,7 +557,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -569,7 +576,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
||||||
|
|
||||||
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
|
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
|
||||||
|
|
||||||
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -579,7 +586,7 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testActualRouteSessionContextInjection() throws InvalidProtocolBufferException {
|
void testActualRouteSessionContextInjection() throws Exception {
|
||||||
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
ResourceConfig resourceConfig = new DropwizardResourceConfig();
|
||||||
resourceConfig.register(new TestResource());
|
resourceConfig.register(new TestResource());
|
||||||
resourceConfig.register(new TestExceptionMapper());
|
resourceConfig.register(new TestExceptionMapper());
|
||||||
|
@ -590,7 +597,8 @@ class WebSocketResourceProviderTest {
|
||||||
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
|
||||||
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
|
||||||
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
|
WebSocketResourceProvider<TestPrincipal> 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);
|
Session session = mock(Session.class);
|
||||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||||
|
@ -622,7 +630,7 @@ class WebSocketResourceProviderTest {
|
||||||
|
|
||||||
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
|
ArgumentCaptor<ByteBuffer> 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);
|
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
|
||||||
|
|
||||||
|
@ -690,12 +698,12 @@ class WebSocketResourceProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private SubProtocol.WebSocketResponseMessage getResponse(ArgumentCaptor<ByteBuffer> responseCaptor)
|
private SubProtocol.WebSocketResponseMessage getResponse(ArgumentCaptor<ByteBuffer> responseCaptor)
|
||||||
throws InvalidProtocolBufferException {
|
throws Exception {
|
||||||
return SubProtocol.WebSocketMessage.parseFrom(responseCaptor.getValue().array()).getResponse();
|
return SubProtocol.WebSocketMessage.parseFrom(responseCaptor.getValue().array()).getResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SubProtocol.WebSocketRequestMessage getRequest(ArgumentCaptor<ByteBuffer> requestCaptor)
|
private SubProtocol.WebSocketRequestMessage getRequest(ArgumentCaptor<ByteBuffer> requestCaptor)
|
||||||
throws InvalidProtocolBufferException {
|
throws Exception {
|
||||||
return SubProtocol.WebSocketMessage.parseFrom(requestCaptor.getValue().array()).getRequest();
|
return SubProtocol.WebSocketMessage.parseFrom(requestCaptor.getValue().array()).getRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import ch.qos.logback.classic.LoggerContext;
|
||||||
import ch.qos.logback.core.OutputStreamAppender;
|
import ch.qos.logback.core.OutputStreamAppender;
|
||||||
import ch.qos.logback.core.spi.DeferredProcessingAware;
|
import ch.qos.logback.core.spi.DeferredProcessingAware;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
import io.dropwizard.logging.AbstractOutputStreamAppenderFactory;
|
import io.dropwizard.logging.common.AbstractOutputStreamAppenderFactory;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
Loading…
Reference in New Issue