diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 82a96089f..6b6e89acb 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -419,7 +419,7 @@ public class WhisperServerService extends Application MAX_MESSAGE_SIZE) { - rejectOver256kibMessageMeter.mark(); - return Response.status(Response.Status.REQUEST_ENTITY_TOO_LARGE).build(); - } - } - - try { - boolean isSyncMessage = source.isPresent() && source.get().isFor(destinationName); - - Optional destination; - - if (!isSyncMessage) destination = accountsManager.get(destinationName); - else destination = source; - - OptionalAccess.verify(source, accessKey, destination); - assert(destination.isPresent()); - - validateCompleteDeviceList(destination.get(), messages.getMessages(), isSyncMessage); - validateRegistrationIds(destination.get(), messages.getMessages()); - - for (IncomingMessage incomingMessage : messages.getMessages()) { - Optional destinationDevice = destination.get().getDevice(incomingMessage.getDestinationDeviceId()); - - if (destinationDevice.isPresent()) { - sendMessage(source, destination.get(), destinationDevice.get(), messages.getTimestamp(), messages.isOnline(), incomingMessage); - } - } - - return Response.ok(new SendMessageResponse(!isSyncMessage && source.isPresent() && source.get().getEnabledDeviceCount() > 1)).build(); - } catch (NoSuchUserException e) { - throw new WebApplicationException(Response.status(404).build()); - } catch (MismatchedDevicesException e) { - throw new WebApplicationException(Response.status(409) - .type(MediaType.APPLICATION_JSON_TYPE) - .entity(new MismatchedDevices(e.getMissingDevices(), - e.getExtraDevices())) - .build()); - } catch (StaleDevicesException e) { - throw new WebApplicationException(Response.status(410) - .type(MediaType.APPLICATION_JSON) - .entity(new StaleDevices(e.getStaleDevices())) - .build()); - } - } else { - if (featureFlagsManager.isFeatureFlagActive("SEND_ALL_200_STATUS")) { - // Forgive me for what I must do - return Response.ok(new SendMessageResponse(false)).build(); - } else { - return Response.status(503).build(); - } - } - } - - private boolean shouldSend(final AmbiguousIdentifier destination) { - final double hash = destination.sendingGateHash(); - - return (hash / 256.0) < getSuccessPercentage(); - } - - private double getSuccessPercentage() { - if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_1_PERCENT")) { - return 0.01; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_2_PERCENT")) { - return 0.02; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_4_PERCENT")) { - return 0.04; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_8_PERCENT")) { - return 0.08; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_16_PERCENT")) { - return 0.16; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_32_PERCENT")) { - return 0.32; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_48_PERCENT")) { - return 0.48; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_64_PERCENT")) { - return 0.64; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_80_PERCENT")) { - return 0.80; - } else if (featureFlagsManager.isFeatureFlagActive("SEND_MESSAGE_100_PERCENT")) { - return 1.0d; + if (source.isPresent() && !source.get().isFor(destinationName)) { + identifiedMeter.mark(); + } else if (source.isEmpty()) { + unidentifiedMeter.mark(); } - return 0; + for (final IncomingMessage message : messages.getMessages()) { + int contentLength = 0; + + if (!Util.isEmpty(message.getContent())) { + contentLength += message.getContent().length(); + } + + if (!Util.isEmpty(message.getBody())) { + contentLength += message.getBody().length(); + } + + Metrics.summary(CONTENT_SIZE_DISTRIBUTION_NAME, UserAgentTagUtil.getUserAgentTags(userAgent)).record(contentLength); + + if (contentLength > MAX_MESSAGE_SIZE) { + rejectOver256kibMessageMeter.mark(); + return Response.status(Response.Status.REQUEST_ENTITY_TOO_LARGE).build(); + } + } + + try { + boolean isSyncMessage = source.isPresent() && source.get().isFor(destinationName); + + Optional destination; + + if (!isSyncMessage) destination = accountsManager.get(destinationName); + else destination = source; + + OptionalAccess.verify(source, accessKey, destination); + assert(destination.isPresent()); + + validateCompleteDeviceList(destination.get(), messages.getMessages(), isSyncMessage); + validateRegistrationIds(destination.get(), messages.getMessages()); + + for (IncomingMessage incomingMessage : messages.getMessages()) { + Optional destinationDevice = destination.get().getDevice(incomingMessage.getDestinationDeviceId()); + + if (destinationDevice.isPresent()) { + sendMessage(source, destination.get(), destinationDevice.get(), messages.getTimestamp(), messages.isOnline(), incomingMessage); + } + } + + return Response.ok(new SendMessageResponse(!isSyncMessage && source.isPresent() && source.get().getEnabledDeviceCount() > 1)).build(); + } catch (NoSuchUserException e) { + throw new WebApplicationException(Response.status(404).build()); + } catch (MismatchedDevicesException e) { + throw new WebApplicationException(Response.status(409) + .type(MediaType.APPLICATION_JSON_TYPE) + .entity(new MismatchedDevices(e.getMissingDevices(), + e.getExtraDevices())) + .build()); + } catch (StaleDevicesException e) { + throw new WebApplicationException(Response.status(410) + .type(MediaType.APPLICATION_JSON) + .entity(new StaleDevices(e.getStaleDevices())) + .build()); + } } @Timed diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java index 8aa99bc62..45f4e9e1f 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java @@ -96,7 +96,7 @@ public class MessageControllerTest { .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>(ImmutableSet.of(Account.class, DisabledPermittedAccount.class))) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new MessageController(rateLimiters, messageSender, receiptSender, accountsManager, - messagesManager, apnFallbackManager, featureFlagsManager)) + messagesManager, apnFallbackManager)) .build();