mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-27 11:33:15 +01:00
109 lines
4.1 KiB
Java
109 lines
4.1 KiB
Java
package org.whispersystems.textsecuregcm.controllers;
|
|
|
|
import com.codahale.metrics.annotation.Timed;
|
|
import com.google.common.base.Optional;
|
|
import org.whispersystems.textsecuregcm.federation.FederatedClientManager;
|
|
import org.whispersystems.textsecuregcm.federation.NoSuchPeerException;
|
|
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
|
import org.whispersystems.textsecuregcm.push.PushSender;
|
|
import org.whispersystems.textsecuregcm.push.TransientPushFailureException;
|
|
import org.whispersystems.textsecuregcm.storage.Account;
|
|
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
|
import org.whispersystems.textsecuregcm.storage.Device;
|
|
|
|
import javax.ws.rs.PUT;
|
|
import javax.ws.rs.Path;
|
|
import javax.ws.rs.PathParam;
|
|
import javax.ws.rs.QueryParam;
|
|
import javax.ws.rs.WebApplicationException;
|
|
import javax.ws.rs.core.Response;
|
|
import java.io.IOException;
|
|
import java.util.Set;
|
|
|
|
import io.dropwizard.auth.Auth;
|
|
import static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
|
|
|
|
@Path("/v1/receipt")
|
|
public class ReceiptController {
|
|
|
|
private final AccountsManager accountManager;
|
|
private final PushSender pushSender;
|
|
private final FederatedClientManager federatedClientManager;
|
|
|
|
public ReceiptController(AccountsManager accountManager,
|
|
FederatedClientManager federatedClientManager,
|
|
PushSender pushSender)
|
|
{
|
|
this.accountManager = accountManager;
|
|
this.federatedClientManager = federatedClientManager;
|
|
this.pushSender = pushSender;
|
|
}
|
|
|
|
@Timed
|
|
@PUT
|
|
@Path("/{destination}/{messageId}")
|
|
public void sendDeliveryReceipt(@Auth Account source,
|
|
@PathParam("destination") String destination,
|
|
@PathParam("messageId") long messageId,
|
|
@QueryParam("relay") Optional<String> relay)
|
|
throws IOException
|
|
{
|
|
try {
|
|
if (relay.isPresent()) sendRelayedReceipt(source, destination, messageId, relay.get());
|
|
else sendDirectReceipt(source, destination, messageId);
|
|
} catch (NoSuchUserException | NotPushRegisteredException e) {
|
|
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
|
} catch (TransientPushFailureException e) {
|
|
throw new IOException(e);
|
|
}
|
|
}
|
|
|
|
private void sendRelayedReceipt(Account source, String destination, long messageId, String relay)
|
|
throws NoSuchUserException, IOException
|
|
{
|
|
try {
|
|
federatedClientManager.getClient(relay)
|
|
.sendDeliveryReceipt(source.getNumber(),
|
|
source.getAuthenticatedDevice().get().getId(),
|
|
destination, messageId);
|
|
} catch (NoSuchPeerException e) {
|
|
throw new NoSuchUserException(e);
|
|
}
|
|
}
|
|
|
|
private void sendDirectReceipt(Account source, String destination, long messageId)
|
|
throws NotPushRegisteredException, TransientPushFailureException, NoSuchUserException
|
|
{
|
|
Account destinationAccount = getDestinationAccount(destination);
|
|
Set<Device> destinationDevices = destinationAccount.getDevices();
|
|
|
|
OutgoingMessageSignal.Builder message =
|
|
OutgoingMessageSignal.newBuilder()
|
|
.setSource(source.getNumber())
|
|
.setSourceDevice((int) source.getAuthenticatedDevice().get().getId())
|
|
.setTimestamp(messageId)
|
|
.setType(OutgoingMessageSignal.Type.RECEIPT_VALUE);
|
|
|
|
if (source.getRelay().isPresent()) {
|
|
message.setRelay(source.getRelay().get());
|
|
}
|
|
|
|
for (Device destinationDevice : destinationDevices) {
|
|
pushSender.sendMessage(destinationAccount, destinationDevice, message.build());
|
|
}
|
|
}
|
|
|
|
private Account getDestinationAccount(String destination)
|
|
throws NoSuchUserException
|
|
{
|
|
Optional<Account> account = accountManager.get(destination);
|
|
|
|
if (!account.isPresent()) {
|
|
throw new NoSuchUserException(destination);
|
|
}
|
|
|
|
return account.get();
|
|
}
|
|
|
|
}
|