diff --git a/gcm-sender-async/pom.xml b/gcm-sender-async/pom.xml
deleted file mode 100644
index dcf32b649..000000000
--- a/gcm-sender-async/pom.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
- TextSecureServer
- org.whispersystems.textsecure
- JGITVER
-
- 4.0.0
- gcm-sender-async
-
-
-
- io.github.resilience4j
- resilience4j-retry
-
-
- com.fasterxml.jackson.core
- jackson-core
-
-
- com.fasterxml.jackson.core
- jackson-annotations
-
-
- com.fasterxml.jackson.core
- jackson-databind
-
-
- com.google.guava
- guava
-
-
- org.apache.httpcomponents
- httpclient
- test
-
-
- org.slf4j
- jcl-over-slf4j
- test
-
-
- org.slf4j
- slf4j-nop
- test
-
-
-
-
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/AuthenticationFailedException.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/AuthenticationFailedException.java
deleted file mode 100644
index 986cc23a7..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/AuthenticationFailedException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-
-public class AuthenticationFailedException extends Exception {
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/InvalidRequestException.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/InvalidRequestException.java
deleted file mode 100644
index e9ea47013..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/InvalidRequestException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-
-public class InvalidRequestException extends Exception {
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Message.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Message.java
deleted file mode 100644
index 038639142..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Message.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.whispersystems.gcm.server.internal.GcmRequestEntity;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-public class Message {
-
- private static final ObjectMapper objectMapper = new ObjectMapper();
-
- private final String collapseKey;
- private final Long ttl;
- private final Boolean delayWhileIdle;
- private final Map data;
- private final List registrationIds;
- private final String priority;
-
- private Message(String collapseKey, Long ttl, Boolean delayWhileIdle,
- Map data, List registrationIds,
- String priority)
- {
- this.collapseKey = collapseKey;
- this.ttl = ttl;
- this.delayWhileIdle = delayWhileIdle;
- this.data = data;
- this.registrationIds = registrationIds;
- this.priority = priority;
- }
-
- public String serialize() throws JsonProcessingException {
- GcmRequestEntity requestEntity = new GcmRequestEntity(collapseKey, ttl, delayWhileIdle,
- data, registrationIds, priority);
-
- return objectMapper.writeValueAsString(requestEntity);
- }
-
- /**
- * Construct a new Message using a Builder.
- * @return A new Builder.
- */
- public static Builder newBuilder() {
- return new Builder();
- }
-
- public static class Builder {
-
- private String collapseKey = null;
- private Long ttl = null;
- private Boolean delayWhileIdle = null;
- private Map data = null;
- private List registrationIds = new LinkedList<>();
- private String priority = null;
-
- private Builder() {}
-
- /**
- * @param collapseKey The GCM collapse key to use (optional).
- * @return The Builder.
- */
- public Builder withCollapseKey(String collapseKey) {
- this.collapseKey = collapseKey;
- return this;
- }
-
- /**
- * @param seconds The TTL (in seconds) for this message (optional).
- * @return The Builder.
- */
- public Builder withTtl(long seconds) {
- this.ttl = seconds;
- return this;
- }
-
- /**
- * @param delayWhileIdle Set GCM delay_while_idle (optional).
- * @return The Builder.
- */
- public Builder withDelayWhileIdle(boolean delayWhileIdle) {
- this.delayWhileIdle = delayWhileIdle;
- return this;
- }
-
- /**
- * Set a key in the GCM JSON payload delivered to the application (optional).
- * @param key The key to set.
- * @param value The value to set.
- * @return The Builder.
- */
- public Builder withDataPart(String key, String value) {
- if (data == null) {
- data = new HashMap<>();
- }
- data.put(key, value);
- return this;
- }
-
- /**
- * Set the destination GCM registration ID (mandatory).
- * @param registrationId The destination GCM registration ID.
- * @return The Builder.
- */
- public Builder withDestination(String registrationId) {
- this.registrationIds.clear();
- this.registrationIds.add(registrationId);
- return this;
- }
-
- /**
- * Set the GCM message priority (optional).
- *
- * @param priority Valid values are "normal" and "high."
- * On iOS, these correspond to APNs priority 5 and 10.
- * @return The Builder.
- */
- public Builder withPriority(String priority) {
- this.priority = priority;
- return this;
- }
-
- /**
- * Construct a message object.
- *
- * @return An immutable message object, as configured by this builder.
- */
- public Message build() {
- if (registrationIds.isEmpty()) {
- throw new IllegalArgumentException("You must specify a destination!");
- }
-
- return new Message(collapseKey, ttl, delayWhileIdle, data, registrationIds, priority);
- }
- }
-
-
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Result.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Result.java
deleted file mode 100644
index b659c3d1b..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Result.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-/**
- * The result of a GCM send operation.
- */
-public class Result {
-
- private final String canonicalRegistrationId;
- private final String messageId;
- private final String error;
-
- Result(String canonicalRegistrationId, String messageId, String error) {
- this.canonicalRegistrationId = canonicalRegistrationId;
- this.messageId = messageId;
- this.error = error;
- }
-
- /**
- * Returns the "canonical" GCM registration ID for this destination.
- * See GCM documentation for details.
- * @return The canonical GCM registration ID.
- */
- public String getCanonicalRegistrationId() {
- return canonicalRegistrationId;
- }
-
- /**
- * @return If a "canonical" GCM registration ID is present in the response.
- */
- public boolean hasCanonicalRegistrationId() {
- return canonicalRegistrationId != null && !canonicalRegistrationId.isEmpty();
- }
-
- /**
- * @return The assigned GCM message ID, if successful.
- */
- public String getMessageId() {
- return messageId;
- }
-
- /**
- * @return The raw error string, if present.
- */
- public String getError() {
- return error;
- }
-
- /**
- * @return If the send was a success.
- */
- public boolean isSuccess() {
- return messageId != null && !messageId.isEmpty() && (error == null || error.isEmpty());
- }
-
- /**
- * @return If the destination GCM registration ID is no longer registered.
- */
- public boolean isUnregistered() {
- return "NotRegistered".equals(error);
- }
-
- /**
- * @return If messages to this device are being throttled.
- */
- public boolean isThrottled() {
- return "DeviceMessageRateExceeded".equals(error);
- }
-
- /**
- * @return If the destination GCM registration ID is invalid.
- */
- public boolean isInvalidRegistrationId() {
- return "InvalidRegistration".equals(error);
- }
-
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Sender.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Sender.java
deleted file mode 100644
index 84fc57769..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/Sender.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.annotations.VisibleForTesting;
-import io.github.resilience4j.core.IntervalFunction;
-import io.github.resilience4j.retry.Retry;
-import io.github.resilience4j.retry.RetryConfig;
-import java.io.IOException;
-import java.net.URI;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.security.SecureRandom;
-import java.time.Duration;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeoutException;
-import org.whispersystems.gcm.server.internal.GcmResponseEntity;
-import org.whispersystems.gcm.server.internal.GcmResponseListEntity;
-
-/**
- * The main interface to sending GCM messages. Thread safe.
- *
- * @author Moxie Marlinspike
- */
-public class Sender {
-
- private static final String PRODUCTION_URL = "https://fcm.googleapis.com/fcm/send";
-
- private final String authorizationHeader;
- private final URI uri;
- private final Retry retry;
- private final ObjectMapper mapper;
- private final ScheduledExecutorService executorService;
-
- private final HttpClient[] clients = new HttpClient[10];
- private final SecureRandom random = new SecureRandom();
-
- /**
- * Construct a Sender instance.
- *
- * @param apiKey Your application's GCM API key.
- */
- public Sender(String apiKey, ObjectMapper mapper) {
- this(apiKey, mapper, 10);
- }
-
- /**
- * Construct a Sender instance with a specified retry count.
- *
- * @param apiKey Your application's GCM API key.
- * @param retryCount The number of retries to attempt on a network error or 500 response.
- */
- public Sender(String apiKey, ObjectMapper mapper, int retryCount) {
- this(apiKey, mapper, retryCount, PRODUCTION_URL);
- }
-
- @VisibleForTesting
- public Sender(String apiKey, ObjectMapper mapper, int retryCount, String url) {
- this.mapper = mapper;
- this.executorService = Executors.newSingleThreadScheduledExecutor();
- this.uri = URI.create(url);
- this.authorizationHeader = String.format("key=%s", apiKey);
- this.retry = Retry.of("fcm-sender", RetryConfig.custom()
- .maxAttempts(retryCount)
- .intervalFunction(IntervalFunction.ofExponentialRandomBackoff(Duration.ofMillis(100), 2.0))
- .retryOnException(this::isRetryableException)
- .build());
-
- for (int i=0;i send(Message message) {
- try {
- HttpRequest request = HttpRequest.newBuilder()
- .uri(uri)
- .header("Authorization", authorizationHeader)
- .header("Content-Type", "application/json")
- .POST(HttpRequest.BodyPublishers.ofString(message.serialize()))
- .timeout(Duration.ofSeconds(10))
- .build();
-
- return retry.executeCompletionStage(executorService,
- () -> getClient().sendAsync(request, BodyHandlers.ofByteArray())
- .thenApply(response -> {
- switch (response.statusCode()) {
- case 400: throw new CompletionException(new InvalidRequestException());
- case 401: throw new CompletionException(new AuthenticationFailedException());
- case 204:
- case 200: return response.body();
- default: throw new CompletionException(new ServerFailedException("Bad status: " + response.statusCode()));
- }
- })
- .thenApply(responseBytes -> {
- try {
- List responseList = mapper.readValue(responseBytes, GcmResponseListEntity.class).getResults();
-
- if (responseList == null || responseList.size() == 0) {
- throw new CompletionException(new IOException("Empty response list!"));
- }
-
- GcmResponseEntity responseEntity = responseList.get(0);
-
- return new Result(responseEntity.getCanonicalRegistrationId(),
- responseEntity.getMessageId(),
- responseEntity.getError());
- } catch (IOException e) {
- throw new CompletionException(e);
- }
- })).toCompletableFuture();
- } catch (JsonProcessingException e) {
- return CompletableFuture.failedFuture(e);
- }
- }
-
- public Retry getRetry() {
- return retry;
- }
-
- private HttpClient getClient() {
- return clients[random.nextInt(clients.length)];
- }
-
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/ServerFailedException.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/ServerFailedException.java
deleted file mode 100644
index 611512109..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/ServerFailedException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-public class ServerFailedException extends Exception {
- public ServerFailedException(String message) {
- super(message);
- }
-
- public ServerFailedException(Exception e) {
- super(e);
- }
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmRequestEntity.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmRequestEntity.java
deleted file mode 100644
index 980c8184d..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmRequestEntity.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server.internal;
-
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.util.List;
-import java.util.Map;
-
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class GcmRequestEntity {
-
- @JsonProperty(value = "collapse_key")
- private String collapseKey;
-
- @JsonProperty(value = "time_to_live")
- private Long ttl;
-
- @JsonProperty(value = "delay_while_idle")
- private Boolean delayWhileIdle;
-
- @JsonProperty(value = "data")
- private Map data;
-
- @JsonProperty(value = "registration_ids")
- private List registrationIds;
-
- @JsonProperty
- private String priority;
-
- public GcmRequestEntity(String collapseKey, Long ttl, Boolean delayWhileIdle,
- Map data, List registrationIds,
- String priority)
- {
- this.collapseKey = collapseKey;
- this.ttl = ttl;
- this.delayWhileIdle = delayWhileIdle;
- this.data = data;
- this.registrationIds = registrationIds;
- this.priority = priority;
- }
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmResponseEntity.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmResponseEntity.java
deleted file mode 100644
index 7683111cd..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmResponseEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server.internal;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class GcmResponseEntity {
-
- @JsonProperty(value = "message_id")
- private String messageId;
-
- @JsonProperty(value = "registration_id")
- private String canonicalRegistrationId;
-
- @JsonProperty
- private String error;
-
- public String getMessageId() {
- return messageId;
- }
-
- public String getCanonicalRegistrationId() {
- return canonicalRegistrationId;
- }
-
- public String getError() {
- return error;
- }
-}
diff --git a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmResponseListEntity.java b/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmResponseListEntity.java
deleted file mode 100644
index 1005f2116..000000000
--- a/gcm-sender-async/src/main/java/org/whispersystems/gcm/server/internal/GcmResponseListEntity.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server.internal;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.util.List;
-
-public class GcmResponseListEntity {
-
- @JsonProperty
- private List results;
-
- public List getResults() {
- return results;
- }
-}
diff --git a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/MessageTest.java b/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/MessageTest.java
deleted file mode 100644
index e62e000a9..000000000
--- a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/MessageTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.whispersystems.gcm.server.util.JsonHelpers.jsonFixture;
-
-import java.io.IOException;
-import org.junit.jupiter.api.Test;
-
-public class MessageTest {
-
- @Test
- void testMinimal() throws IOException {
- Message message = Message.newBuilder()
- .withDestination("1")
- .build();
-
- assertEquals(message.serialize(), jsonFixture("fixtures/message-minimal.json"));
- }
-
- @Test
- void testComplete() throws IOException {
- Message message = Message.newBuilder()
- .withDestination("1")
- .withCollapseKey("collapse")
- .withDelayWhileIdle(true)
- .withTtl(10)
- .withPriority("high")
- .build();
-
- assertEquals(message.serialize(), jsonFixture("fixtures/message-complete.json"));
- }
-
- @Test
- void testWithData() throws IOException {
- Message message = Message.newBuilder()
- .withDestination("2")
- .withDataPart("key1", "value1")
- .withDataPart("key2", "value2")
- .build();
-
- assertEquals(message.serialize(), jsonFixture("fixtures/message-data.json"));
- }
-
-}
diff --git a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/SenderTest.java b/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/SenderTest.java
deleted file mode 100644
index e2d9dcd1f..000000000
--- a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/SenderTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.any;
-import static com.github.tomakehurst.wiremock.client.WireMock.anyRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.ok;
-import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.whispersystems.gcm.server.util.FixtureHelpers.fixture;
-import static org.whispersystems.gcm.server.util.JsonHelpers.jsonFixture;
-
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.github.tomakehurst.wiremock.client.CountMatchingStrategy;
-import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
-import java.io.IOException;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class SenderTest {
-
- @RegisterExtension
- private final WireMockExtension wireMock = WireMockExtension.newInstance()
- .options(wireMockConfig().dynamicPort().dynamicHttpsPort())
- .build();
-
- private static final ObjectMapper mapper = new ObjectMapper();
-
- static {
- mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
- mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- }
-
- @Test
- void testSuccess() throws InterruptedException, ExecutionException, TimeoutException, IOException {
- wireMock.stubFor(any(anyUrl())
- .willReturn(aResponse()
- .withStatus(200)
- .withBody(fixture("fixtures/response-success.json"))));
-
-
- Sender sender = new Sender("foobarbaz", mapper, 10, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- CompletableFuture future = sender.send(Message.newBuilder().withDestination("1").build());
-
- Result result = future.get(10, TimeUnit.SECONDS);
-
- assertTrue(result.isSuccess());
- assertFalse(result.isThrottled());
- assertFalse(result.isUnregistered());
- assertEquals(result.getMessageId(), "1:08");
- assertNull(result.getError());
- assertNull(result.getCanonicalRegistrationId());
-
- wireMock.verify(1, postRequestedFor(urlEqualTo("/gcm/send"))
- .withHeader("Authorization", equalTo("key=foobarbaz"))
- .withHeader("Content-Type", equalTo("application/json"))
- .withRequestBody(equalTo(jsonFixture("fixtures/message-minimal.json"))));
- }
-
- @Test
- void testBadApiKey() throws InterruptedException, TimeoutException {
- wireMock.stubFor(any(anyUrl())
- .willReturn(aResponse()
- .withStatus(401)));
-
- Sender sender = new Sender("foobar", mapper, 10, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- CompletableFuture future = sender.send(Message.newBuilder().withDestination("1").build());
-
- try {
- future.get(10, TimeUnit.SECONDS);
- throw new AssertionError();
- } catch (ExecutionException ee) {
- assertTrue(ee.getCause() instanceof AuthenticationFailedException);
- }
-
- wireMock.verify(1, anyRequestedFor(anyUrl()));
- }
-
- @Test
- void testBadRequest() throws TimeoutException, InterruptedException {
- wireMock.stubFor(any(anyUrl())
- .willReturn(aResponse()
- .withStatus(400)));
-
- Sender sender = new Sender("foobarbaz", mapper, 10, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- CompletableFuture future = sender.send(Message.newBuilder().withDestination("1").build());
-
- try {
- future.get(10, TimeUnit.SECONDS);
- throw new AssertionError();
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof InvalidRequestException);
- }
-
- wireMock.verify(1, anyRequestedFor(anyUrl()));
- }
-
- @Test
- void testServerError() throws TimeoutException, InterruptedException {
- wireMock.stubFor(any(anyUrl())
- .willReturn(aResponse()
- .withStatus(503)));
-
- Sender sender = new Sender("foobarbaz", mapper, 3, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- CompletableFuture future = sender.send(Message.newBuilder().withDestination("1").build());
-
- try {
- future.get(10, TimeUnit.SECONDS);
- throw new AssertionError();
- } catch (ExecutionException ee) {
- assertTrue(ee.getCause() instanceof ServerFailedException);
- }
-
- wireMock.verify(3, anyRequestedFor(anyUrl()));
- }
-
- @Test
- void testServerErrorRecovery() throws InterruptedException, ExecutionException, TimeoutException {
-
- wireMock.stubFor(any(anyUrl()).willReturn(aResponse().withStatus(503)));
-
- Sender sender = new Sender("foobarbaz", mapper, 4, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- CompletableFuture future = sender.send(Message.newBuilder().withDestination("1").build());
-
- // up to three failures can happen, with 100ms exponential backoff
- // if we end up using the fourth, and final try, it would be after ~700 ms
- CompletableFuture.delayedExecutor(300, TimeUnit.MILLISECONDS).execute(() ->
- wireMock.stubFor(any(anyUrl())
- .willReturn(aResponse()
- .withStatus(200)
- .withBody(fixture("fixtures/response-success.json"))))
- );
-
- Result result = future.get(10, TimeUnit.SECONDS);
-
- wireMock.verify(new CountMatchingStrategy(CountMatchingStrategy.GREATER_THAN, 1), anyRequestedFor(anyUrl()));
- assertTrue(result.isSuccess());
- assertFalse(result.isThrottled());
- assertFalse(result.isUnregistered());
- assertEquals(result.getMessageId(), "1:08");
- assertNull(result.getError());
- assertNull(result.getCanonicalRegistrationId());
- }
-
- @Test
- void testNetworkError() throws TimeoutException, InterruptedException {
-
- wireMock.stubFor(any(anyUrl())
- .willReturn(ok()));
-
- Sender sender = new Sender("foobarbaz", mapper ,2, "http://localhost:" + wireMock.getPort() + "/gcm/send");
-
- wireMock.getRuntimeInfo().getWireMock().shutdown();
-
- CompletableFuture future = sender.send(Message.newBuilder().withDestination("1").build());
-
- try {
- future.get(10, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof IOException);
- }
- }
-
- @Test
- void testNotRegistered() throws InterruptedException, ExecutionException, TimeoutException {
-
- wireMock.stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200)
- .withBody(fixture("fixtures/response-not-registered.json"))));
-
- Sender sender = new Sender("foobarbaz", mapper,2, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- CompletableFuture future = sender.send(Message.newBuilder()
- .withDestination("2")
- .withDataPart("message", "new message!")
- .build());
-
- Result result = future.get(10, TimeUnit.SECONDS);
-
- assertFalse(result.isSuccess());
- assertTrue(result.isUnregistered());
- assertFalse(result.isThrottled());
- assertEquals(result.getError(), "NotRegistered");
- }
-}
diff --git a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/SimultaneousSenderTest.java b/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/SimultaneousSenderTest.java
deleted file mode 100644
index a5fcf958e..000000000
--- a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/SimultaneousSenderTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.post;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.whispersystems.gcm.server.util.FixtureHelpers.fixture;
-
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class SimultaneousSenderTest {
-
- @RegisterExtension
- private final WireMockExtension wireMock = WireMockExtension.newInstance()
- .options(wireMockConfig().dynamicPort().dynamicHttpsPort())
- .build();
-
- private static final ObjectMapper mapper = new ObjectMapper();
-
- static {
- mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
- mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- }
-
- @Test
- void testSimultaneousSuccess() throws TimeoutException, InterruptedException, ExecutionException {
- wireMock.stubFor(post(urlPathEqualTo("/gcm/send"))
- .willReturn(aResponse()
- .withStatus(200)
- .withBody(fixture("fixtures/response-success.json"))));
-
- Sender sender = new Sender("foobarbaz", mapper, 2, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- List> results = new LinkedList<>();
-
- for (int i=0;i<1000;i++) {
- results.add(sender.send(Message.newBuilder().withDestination("1").build()));
- }
-
- for (CompletableFuture future : results) {
- Result result = future.get(60, TimeUnit.SECONDS);
-
- if (!result.isSuccess()) {
- throw new AssertionError(result.getError());
- }
- }
- }
-
- @Test
- @Disabled
- void testSimultaneousFailure() {
- wireMock.stubFor(post(urlPathEqualTo("/gcm/send"))
- .willReturn(aResponse()
- .withStatus(503)));
-
- Sender sender = new Sender("foobarbaz", mapper, 2, "http://localhost:" + wireMock.getPort() + "/gcm/send");
- List> futures = new LinkedList<>();
-
- for (int i=0;i<1000;i++) {
- futures.add(sender.send(Message.newBuilder().withDestination("1").build()));
- }
-
- for (CompletableFuture future : futures) {
- final ExecutionException e = assertThrows(ExecutionException.class, () -> future.get(60, TimeUnit.SECONDS));
-
- assertTrue(e.getCause() instanceof ServerFailedException, e.getCause().toString());
- }
- }
-}
diff --git a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/util/FixtureHelpers.java b/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/util/FixtureHelpers.java
deleted file mode 100644
index 994beae62..000000000
--- a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/util/FixtureHelpers.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server.util;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Resources;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-
-/**
- * A set of helper method for fixture files.
- */
-public class FixtureHelpers {
- private FixtureHelpers() { /* singleton */ }
-
- /**
- * Reads the given fixture file from the classpath (e. g. {@code src/test/resources})
- * and returns its contents as a UTF-8 string.
- *
- * @param filename the filename of the fixture file
- * @return the contents of {@code src/test/resources/{filename}}
- * @throws IllegalArgumentException if an I/O error occurs.
- */
- public static String fixture(String filename) {
- return fixture(filename, Charsets.UTF_8);
- }
-
- /**
- * Reads the given fixture file from the classpath (e. g. {@code src/test/resources})
- * and returns its contents as a string.
- *
- * @param filename the filename of the fixture file
- * @param charset the character set of {@code filename}
- * @return the contents of {@code src/test/resources/{filename}}
- * @throws IllegalArgumentException if an I/O error occurs.
- */
- private static String fixture(String filename, Charset charset) {
- try {
- return Resources.toString(Resources.getResource(filename), charset).trim();
- } catch (IOException e) {
- throw new IllegalArgumentException(e);
- }
- }
-}
diff --git a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/util/JsonHelpers.java b/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/util/JsonHelpers.java
deleted file mode 100644
index e71cec4bf..000000000
--- a/gcm-sender-async/src/test/java/org/whispersystems/gcm/server/util/JsonHelpers.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2013-2020 Signal Messenger, LLC
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-package org.whispersystems.gcm.server.util;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.io.IOException;
-
-import static org.whispersystems.gcm.server.util.FixtureHelpers.fixture;
-
-public class JsonHelpers {
-
- private static final ObjectMapper objectMapper = new ObjectMapper();
-
- public static String asJson(Object object) throws JsonProcessingException {
- return objectMapper.writeValueAsString(object);
- }
-
- public static T fromJson(String value, Class clazz) throws IOException {
- return objectMapper.readValue(value, clazz);
- }
-
- public static String jsonFixture(String filename) throws IOException {
- return objectMapper.writeValueAsString(objectMapper.readValue(fixture(filename), JsonNode.class));
- }
-}
diff --git a/gcm-sender-async/src/test/resources/fixtures/message-complete.json b/gcm-sender-async/src/test/resources/fixtures/message-complete.json
deleted file mode 100644
index 43a4dcf06..000000000
--- a/gcm-sender-async/src/test/resources/fixtures/message-complete.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "priority" : "high",
- "collapse_key" : "collapse",
- "time_to_live" : 10,
- "delay_while_idle" : true,
- "registration_ids" : ["1"]
-}
\ No newline at end of file
diff --git a/gcm-sender-async/src/test/resources/fixtures/message-data.json b/gcm-sender-async/src/test/resources/fixtures/message-data.json
deleted file mode 100644
index 4993e04e4..000000000
--- a/gcm-sender-async/src/test/resources/fixtures/message-data.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "data" : {
- "key1" : "value1",
- "key2" : "value2"
- },
- "registration_ids" : ["2"]
-}
\ No newline at end of file
diff --git a/gcm-sender-async/src/test/resources/fixtures/message-minimal.json b/gcm-sender-async/src/test/resources/fixtures/message-minimal.json
deleted file mode 100644
index 2aab43b01..000000000
--- a/gcm-sender-async/src/test/resources/fixtures/message-minimal.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "registration_ids" : ["1"]
-}
\ No newline at end of file
diff --git a/gcm-sender-async/src/test/resources/fixtures/response-not-registered.json b/gcm-sender-async/src/test/resources/fixtures/response-not-registered.json
deleted file mode 100644
index 9363c9d72..000000000
--- a/gcm-sender-async/src/test/resources/fixtures/response-not-registered.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "multicast_id": 216,
- "success": 0,
- "failure": 1,
- "canonical_ids": 0,
- "results": [
- { "error": "NotRegistered"}
- ]
-}
\ No newline at end of file
diff --git a/gcm-sender-async/src/test/resources/fixtures/response-success.json b/gcm-sender-async/src/test/resources/fixtures/response-success.json
deleted file mode 100644
index 7ae2b3d96..000000000
--- a/gcm-sender-async/src/test/resources/fixtures/response-success.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{ "multicast_id": 108,
- "success": 1,
- "failure": 0,
- "canonical_ids": 0,
- "results": [
- { "message_id": "1:08" }
- ]
-}
\ No newline at end of file
diff --git a/gcm-sender-async/src/test/resources/logback-test.xml b/gcm-sender-async/src/test/resources/logback-test.xml
deleted file mode 100644
index 2b693894a..000000000
--- a/gcm-sender-async/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/pom.xml b/pom.xml
index 094277a19..8e2db41e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,7 +37,6 @@
redis-dispatch
websocket-resources
- gcm-sender-async
service
diff --git a/service/pom.xml b/service/pom.xml
index 2f6561cb6..879cf92b9 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -34,11 +34,6 @@
websocket-resources
${project.version}
-
- org.whispersystems.textsecure
- gcm-sender-async
- ${project.version}
-
org.signal
libsignal-server