mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 23:08:01 +01:00
Clarify behavioral contract of the pre-key store
This commit is contained in:
@@ -21,7 +21,6 @@ import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.KeyRecord;
|
||||
import org.whispersystems.textsecuregcm.storage.KeysDynamoDb;
|
||||
|
||||
import javax.validation.Valid;
|
||||
@@ -35,8 +34,10 @@ import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
@@ -120,28 +121,22 @@ public class KeysController {
|
||||
rateLimiters.getPreKeysLimiter().validate(account.get().getNumber() + "." + account.get().getAuthenticatedDevice().get().getId() + "__" + target.get().getNumber() + "." + deviceId);
|
||||
}
|
||||
|
||||
List<KeyRecord> targetKeys = getLocalKeys(target.get(), deviceId);
|
||||
List<PreKeyResponseItem> devices = new LinkedList<>();
|
||||
Map<Long, PreKey> preKeysByDeviceId = getLocalKeys(target.get(), deviceId);
|
||||
List<PreKeyResponseItem> responseItems = new LinkedList<>();
|
||||
|
||||
for (Device device : target.get().getDevices()) {
|
||||
if (device.isEnabled() && (deviceId.equals("*") || device.getId() == Long.parseLong(deviceId))) {
|
||||
SignedPreKey signedPreKey = device.getSignedPreKey();
|
||||
PreKey preKey = null;
|
||||
|
||||
for (KeyRecord keyRecord : targetKeys) {
|
||||
if (keyRecord.getDeviceId() == device.getId()) {
|
||||
preKey = new PreKey(keyRecord.getKeyId(), keyRecord.getPublicKey());
|
||||
}
|
||||
}
|
||||
PreKey preKey = preKeysByDeviceId.get(device.getId());
|
||||
|
||||
if (signedPreKey != null || preKey != null) {
|
||||
devices.add(new PreKeyResponseItem(device.getId(), device.getRegistrationId(), signedPreKey, preKey));
|
||||
responseItems.add(new PreKeyResponseItem(device.getId(), device.getRegistrationId(), signedPreKey, preKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (devices.isEmpty()) return Optional.empty();
|
||||
else return Optional.of(new PreKeyResponse(target.get().getIdentityKey(), devices));
|
||||
if (responseItems.isEmpty()) return Optional.empty();
|
||||
else return Optional.of(new PreKeyResponse(target.get().getIdentityKey(), responseItems));
|
||||
}
|
||||
|
||||
@Timed
|
||||
@@ -172,7 +167,7 @@ public class KeysController {
|
||||
else return Optional.empty();
|
||||
}
|
||||
|
||||
private List<KeyRecord> getLocalKeys(Account destination, String deviceIdSelector) {
|
||||
private Map<Long, PreKey> getLocalKeys(Account destination, String deviceIdSelector) {
|
||||
try {
|
||||
if (deviceIdSelector.equals("*")) {
|
||||
return keysDynamoDb.take(destination);
|
||||
@@ -180,7 +175,9 @@ public class KeysController {
|
||||
|
||||
long deviceId = Long.parseLong(deviceIdSelector);
|
||||
|
||||
return keysDynamoDb.take(destination, deviceId);
|
||||
return keysDynamoDb.take(destination, deviceId)
|
||||
.map(preKey -> Map.of(deviceId, preKey))
|
||||
.orElse(Collections.emptyMap());
|
||||
} catch (NumberFormatException e) {
|
||||
throw new WebApplicationException(Response.status(422).build());
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.storage;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class KeyRecord {
|
||||
|
||||
private long id;
|
||||
private String number;
|
||||
private long deviceId;
|
||||
private long keyId;
|
||||
private String publicKey;
|
||||
|
||||
public KeyRecord(long id, String number, long deviceId, long keyId, String publicKey) {
|
||||
this.id = id;
|
||||
this.number = number;
|
||||
this.deviceId = deviceId;
|
||||
this.keyId = keyId;
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public long getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public long getKeyId() {
|
||||
return keyId;
|
||||
}
|
||||
|
||||
public String getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final KeyRecord keyRecord = (KeyRecord)o;
|
||||
return id == keyRecord.id &&
|
||||
deviceId == keyRecord.deviceId &&
|
||||
keyId == keyRecord.keyId &&
|
||||
Objects.equals(number, keyRecord.number) &&
|
||||
Objects.equals(publicKey, keyRecord.publicKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, number, deviceId, keyId, publicKey);
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,10 @@ import org.whispersystems.textsecuregcm.util.UUIDUtil;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.codahale.metrics.MetricRegistry.name;
|
||||
@@ -69,7 +71,7 @@ public class KeysDynamoDb extends AbstractDynamoDbStore {
|
||||
});
|
||||
}
|
||||
|
||||
public List<KeyRecord> take(final Account account, final long deviceId) {
|
||||
public Optional<PreKey> take(final Account account, final long deviceId) {
|
||||
return TAKE_KEY_FOR_DEVICE_TIMER.record(() -> {
|
||||
final byte[] partitionKey = getPartitionKey(account.getUuid());
|
||||
|
||||
@@ -90,29 +92,28 @@ public class KeysDynamoDb extends AbstractDynamoDbStore {
|
||||
final DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec);
|
||||
|
||||
if (outcome.getItem() != null) {
|
||||
final PreKey preKey = getPreKeyFromItem(outcome.getItem());
|
||||
return List.of(new KeyRecord(-1, account.getNumber(), deviceId, preKey.getKeyId(), preKey.getPublicKey()));
|
||||
return Optional.of(getPreKeyFromItem(outcome.getItem()));
|
||||
}
|
||||
|
||||
contestedKeys++;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
return Optional.empty();
|
||||
} finally {
|
||||
CONTESTED_KEY_DISTRIBUTION.record(contestedKeys);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<KeyRecord> take(final Account account) {
|
||||
public Map<Long, PreKey> take(final Account account) {
|
||||
return TAKE_KEYS_FOR_ACCOUNT_TIMER.record(() -> {
|
||||
final List<KeyRecord> keyRecords = new ArrayList<>();
|
||||
final Map<Long, PreKey> preKeysByDeviceId = new HashMap<>();
|
||||
|
||||
for (final Device device : account.getDevices()) {
|
||||
keyRecords.addAll(take(account, device.getId()));
|
||||
take(account, device.getId()).ifPresent(preKey -> preKeysByDeviceId.put(device.getId(), preKey));
|
||||
}
|
||||
|
||||
return keyRecords;
|
||||
return preKeysByDeviceId;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.storage.mappers;
|
||||
|
||||
import org.jdbi.v3.core.mapper.RowMapper;
|
||||
import org.jdbi.v3.core.statement.StatementContext;
|
||||
import org.whispersystems.textsecuregcm.storage.KeyRecord;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class KeyRecordRowMapper implements RowMapper<KeyRecord> {
|
||||
|
||||
@Override
|
||||
public KeyRecord map(ResultSet resultSet, StatementContext ctx) throws SQLException {
|
||||
return new KeyRecord(resultSet.getLong("id"),
|
||||
resultSet.getString("number"),
|
||||
resultSet.getLong("device_id"),
|
||||
resultSet.getLong("key_id"),
|
||||
resultSet.getString("public_key"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user