Require CDN number match rather than use default CDN
This marks messages as failed if the CDN number does not match a configured CDN number rather than falling back to the default CDN in the event the CDN is not recognized.
This commit is contained in:
parent
f12a9b9ac7
commit
456bcf3d57
11 changed files with 176 additions and 119 deletions
|
@ -36,17 +36,17 @@ public class ApplicationDependencies {
|
|||
private static Application application;
|
||||
private static Provider provider;
|
||||
|
||||
private static SignalServiceAccountManager accountManager;
|
||||
private static SignalServiceMessageSender messageSender;
|
||||
private static SignalServiceMessageReceiver messageReceiver;
|
||||
private static IncomingMessageProcessor incomingMessageProcessor;
|
||||
private static MessageRetriever messageRetriever;
|
||||
private static LiveRecipientCache recipientCache;
|
||||
private static JobManager jobManager;
|
||||
private static FrameRateTracker frameRateTracker;
|
||||
private static KeyValueStore keyValueStore;
|
||||
private static MegaphoneRepository megaphoneRepository;
|
||||
private static GroupsV2Operations groupsV2Operations;
|
||||
private static SignalServiceAccountManager accountManager;
|
||||
private static SignalServiceMessageSender messageSender;
|
||||
private static SignalServiceMessageReceiver messageReceiver;
|
||||
private static IncomingMessageProcessor incomingMessageProcessor;
|
||||
private static MessageRetriever messageRetriever;
|
||||
private static LiveRecipientCache recipientCache;
|
||||
private static JobManager jobManager;
|
||||
private static FrameRateTracker frameRateTracker;
|
||||
private static KeyValueStore keyValueStore;
|
||||
private static MegaphoneRepository megaphoneRepository;
|
||||
private static GroupsV2Operations groupsV2Operations;
|
||||
|
||||
public static synchronized void init(@NonNull Application application, @NonNull Provider provider) {
|
||||
if (ApplicationDependencies.application != null || ApplicationDependencies.provider != null) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
|||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
|
@ -168,7 +169,7 @@ public class AttachmentDownloadJob extends BaseJob {
|
|||
InputStream stream = messageReceiver.retrieveAttachment(pointer, attachmentFile, MAX_ATTACHMENT_SIZE, (total, progress) -> EventBus.getDefault().postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.NETWORK, total, progress)));
|
||||
|
||||
database.insertAttachmentsForPlaceholder(messageId, attachmentId, stream);
|
||||
} catch (InvalidPartException | NonSuccessfulResponseCodeException | InvalidMessageException | MmsException e) {
|
||||
} catch (InvalidPartException | NonSuccessfulResponseCodeException | InvalidMessageException | MmsException | MissingConfigurationException e) {
|
||||
Log.w(TAG, "Experienced exception while trying to download an attachment.", e);
|
||||
markFailed(messageId, attachmentId);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
|||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -92,7 +93,7 @@ public final class AvatarGroupsV1DownloadJob extends BaseJob {
|
|||
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (NonSuccessfulResponseCodeException | InvalidMessageException e) {
|
||||
} catch (NonSuccessfulResponseCodeException | InvalidMessageException | MissingConfigurationException e) {
|
||||
Log.w(TAG, e);
|
||||
} finally {
|
||||
if (attachment != null)
|
||||
|
|
|
@ -174,8 +174,8 @@ public class SignalServiceNetworkAccess {
|
|||
|
||||
this.censorshipConfiguration = new HashMap<String, SignalServiceConfiguration>() {{
|
||||
put(COUNTRY_CODE_EGYPT, new SignalServiceConfiguration(new SignalServiceUrl[] {egyptGoogleService, baseGoogleService, baseAndroidService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {egyptGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {egyptGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2, mailAndroidCdn2},
|
||||
makeSignalCdnUrlMapFor(new SignalCdnUrl[] {egyptGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {egyptGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2, mailAndroidCdn2}),
|
||||
new SignalContactDiscoveryUrl[] {egyptGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery},
|
||||
new SignalKeyBackupServiceUrl[] {egyptGoogleKbs, baseGoogleKbs, baseAndroidKbs, mapsOneAndroidKbs, mapsTwoAndroidKbs, mailAndroidKbs},
|
||||
new SignalStorageUrl[] {egyptGoogleStorage, baseGoogleStorage, baseAndroidStorage, mapsOneAndroidStorage, mapsTwoAndroidStorage, mailAndroidStorage},
|
||||
|
@ -184,8 +184,8 @@ public class SignalServiceNetworkAccess {
|
|||
zkGroupServerPublicParams));
|
||||
|
||||
put(COUNTRY_CODE_UAE, new SignalServiceConfiguration(new SignalServiceUrl[] {uaeGoogleService, baseAndroidService, baseGoogleService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {uaeGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {uaeGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2},
|
||||
makeSignalCdnUrlMapFor(new SignalCdnUrl[] {uaeGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {uaeGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2}),
|
||||
new SignalContactDiscoveryUrl[] {uaeGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery},
|
||||
new SignalKeyBackupServiceUrl[] {uaeGoogleKbs, baseGoogleKbs, baseAndroidKbs, mapsOneAndroidKbs, mapsTwoAndroidKbs, mailAndroidKbs},
|
||||
new SignalStorageUrl[] {uaeGoogleStorage, baseGoogleStorage, baseAndroidStorage, mapsOneAndroidStorage, mapsTwoAndroidStorage, mailAndroidStorage},
|
||||
|
@ -194,8 +194,8 @@ public class SignalServiceNetworkAccess {
|
|||
zkGroupServerPublicParams));
|
||||
|
||||
put(COUNTRY_CODE_OMAN, new SignalServiceConfiguration(new SignalServiceUrl[] {omanGoogleService, baseAndroidService, baseGoogleService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {omanGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {omanGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2},
|
||||
makeSignalCdnUrlMapFor(new SignalCdnUrl[] {omanGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {omanGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2}),
|
||||
new SignalContactDiscoveryUrl[] {omanGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery},
|
||||
new SignalKeyBackupServiceUrl[] {omanGoogleKbs, baseGoogleKbs, baseAndroidKbs, mapsOneAndroidKbs, mapsTwoAndroidKbs, mailAndroidKbs},
|
||||
new SignalStorageUrl[] {omanGoogleStorage, baseGoogleStorage, baseAndroidStorage, mapsOneAndroidStorage, mapsTwoAndroidStorage, mailAndroidStorage},
|
||||
|
@ -205,8 +205,8 @@ public class SignalServiceNetworkAccess {
|
|||
|
||||
|
||||
put(COUNTRY_CODE_QATAR, new SignalServiceConfiguration(new SignalServiceUrl[] {qatarGoogleService, baseAndroidService, baseGoogleService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {qatarGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {qatarGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2},
|
||||
makeSignalCdnUrlMapFor(new SignalCdnUrl[] {qatarGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalCdnUrl[] {qatarGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2}),
|
||||
new SignalContactDiscoveryUrl[] {qatarGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery},
|
||||
new SignalKeyBackupServiceUrl[] {qatarGoogleKbs, baseGoogleKbs, baseAndroidKbs, mapsOneAndroidKbs, mapsTwoAndroidKbs, mailAndroidKbs},
|
||||
new SignalStorageUrl[] {qatarGoogleStorage, baseGoogleStorage, baseAndroidStorage, mapsOneAndroidStorage, mapsTwoAndroidStorage, mailAndroidStorage},
|
||||
|
@ -216,8 +216,8 @@ public class SignalServiceNetworkAccess {
|
|||
}};
|
||||
|
||||
this.uncensoredConfiguration = new SignalServiceConfiguration(new SignalServiceUrl[] {new SignalServiceUrl(BuildConfig.SIGNAL_URL, new SignalServiceTrustStore(context))},
|
||||
new SignalCdnUrl[] {new SignalCdnUrl(BuildConfig.SIGNAL_CDN_URL, new SignalServiceTrustStore(context))},
|
||||
new SignalCdnUrl[] {new SignalCdnUrl(BuildConfig.SIGNAL_CDN2_URL, new SignalServiceTrustStore(context))},
|
||||
makeSignalCdnUrlMapFor(new SignalCdnUrl[] {new SignalCdnUrl(BuildConfig.SIGNAL_CDN_URL, new SignalServiceTrustStore(context))},
|
||||
new SignalCdnUrl[] {new SignalCdnUrl(BuildConfig.SIGNAL_CDN2_URL, new SignalServiceTrustStore(context))}),
|
||||
new SignalContactDiscoveryUrl[] {new SignalContactDiscoveryUrl(BuildConfig.SIGNAL_CONTACT_DISCOVERY_URL, new SignalServiceTrustStore(context))},
|
||||
new SignalKeyBackupServiceUrl[] { new SignalKeyBackupServiceUrl(BuildConfig.SIGNAL_KEY_BACKUP_URL, new SignalServiceTrustStore(context)) },
|
||||
new SignalStorageUrl[] {new SignalStorageUrl(BuildConfig.STORAGE_URL, new SignalServiceTrustStore(context))},
|
||||
|
@ -253,4 +253,10 @@ public class SignalServiceNetworkAccess {
|
|||
return getConfiguration(number) != this.uncensoredConfiguration;
|
||||
}
|
||||
|
||||
private static Map<Integer, SignalCdnUrl[]> makeSignalCdnUrlMapFor(SignalCdnUrl[] cdn0Urls, SignalCdnUrl[] cdn2Urls) {
|
||||
Map<Integer, SignalCdnUrl[]> result = new HashMap<>();
|
||||
result.put(0, cdn0Urls);
|
||||
result.put(2, cdn2Urls);
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.whispersystems.signalservice.FeatureFlags;
|
|||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream;
|
||||
import org.whispersystems.signalservice.api.crypto.ProfileCipherInputStream;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
|
@ -25,6 +24,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifes
|
|||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
|
@ -118,8 +118,7 @@ public class SignalServiceMessageReceiver {
|
|||
* @throws InvalidMessageException
|
||||
*/
|
||||
public InputStream retrieveAttachment(SignalServiceAttachmentPointer pointer, File destination, long maxSizeBytes)
|
||||
throws IOException, InvalidMessageException
|
||||
{
|
||||
throws IOException, InvalidMessageException, MissingConfigurationException {
|
||||
return retrieveAttachment(pointer, destination, maxSizeBytes, null);
|
||||
}
|
||||
|
||||
|
@ -174,8 +173,7 @@ public class SignalServiceMessageReceiver {
|
|||
* @throws InvalidMessageException
|
||||
*/
|
||||
public InputStream retrieveAttachment(SignalServiceAttachmentPointer pointer, File destination, long maxSizeBytes, ProgressListener listener)
|
||||
throws IOException, InvalidMessageException
|
||||
{
|
||||
throws IOException, InvalidMessageException, MissingConfigurationException {
|
||||
if (!pointer.getDigest().isPresent()) throw new InvalidMessageException("No attachment digest!");
|
||||
|
||||
socket.retrieveAttachment(pointer.getCdnNumber(), pointer.getRemoteId(), destination, maxSizeBytes, listener);
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
|
||||
import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageProtocolVersionException;
|
||||
import org.whispersystems.signalservice.internal.serialize.SignalServiceAddressProtobufSerializer;
|
||||
import org.whispersystems.signalservice.internal.serialize.SignalServiceMetadataProtobufSerializer;
|
||||
import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceContentProto;
|
||||
|
@ -268,7 +269,8 @@ public final class SignalServiceContent {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static SignalServiceDataMessage createSignalServiceMessage(SignalServiceMetadata metadata, SignalServiceProtos.DataMessage content)
|
||||
private static SignalServiceDataMessage createSignalServiceMessage(SignalServiceMetadata metadata,
|
||||
SignalServiceProtos.DataMessage content)
|
||||
throws ProtocolInvalidMessageException, UnsupportedDataMessageException
|
||||
{
|
||||
SignalServiceGroup groupInfoV1 = createGroupV1Info(content);
|
||||
|
@ -292,12 +294,12 @@ public final class SignalServiceContent {
|
|||
SignalServiceDataMessage.Sticker sticker = createSticker(content);
|
||||
SignalServiceDataMessage.Reaction reaction = createReaction(content);
|
||||
|
||||
if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber()) {
|
||||
throw new UnsupportedDataMessageException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber(),
|
||||
content.getRequiredProtocolVersion(),
|
||||
metadata.getSender().getIdentifier(),
|
||||
metadata.getSenderDevice(),
|
||||
groupContext);
|
||||
if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE) {
|
||||
throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE,
|
||||
content.getRequiredProtocolVersion(),
|
||||
metadata.getSender().getIdentifier(),
|
||||
metadata.getSenderDevice(),
|
||||
groupContext);
|
||||
}
|
||||
|
||||
for (SignalServiceProtos.AttachmentPointer pointer : content.getAttachmentsList()) {
|
||||
|
@ -327,7 +329,8 @@ public final class SignalServiceContent {
|
|||
reaction);
|
||||
}
|
||||
|
||||
private static SignalServiceSyncMessage createSynchronizeMessage(SignalServiceMetadata metadata, SignalServiceProtos.SyncMessage content)
|
||||
private static SignalServiceSyncMessage createSynchronizeMessage(SignalServiceMetadata metadata,
|
||||
SignalServiceProtos.SyncMessage content)
|
||||
throws ProtocolInvalidMessageException, ProtocolInvalidKeyException, UnsupportedDataMessageException
|
||||
{
|
||||
if (content.hasSent()) {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package org.whispersystems.signalservice.api.push.exceptions;
|
||||
|
||||
public final class MissingConfigurationException extends Exception {
|
||||
public MissingConfigurationException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
|
@ -3,25 +3,24 @@ package org.whispersystems.signalservice.internal.configuration;
|
|||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Dns;
|
||||
import okhttp3.Interceptor;
|
||||
|
||||
public final class SignalServiceConfiguration {
|
||||
|
||||
private final SignalServiceUrl[] signalServiceUrls;
|
||||
private final SignalCdnUrl[] signalCdnUrls;
|
||||
private final SignalCdnUrl[] signalCdn2Urls;
|
||||
private final SignalContactDiscoveryUrl[] signalContactDiscoveryUrls;
|
||||
private final SignalKeyBackupServiceUrl[] signalKeyBackupServiceUrls;
|
||||
private final SignalStorageUrl[] signalStorageUrls;
|
||||
private final List<Interceptor> networkInterceptors;
|
||||
private final Optional<Dns> dns;
|
||||
private final byte[] zkGroupServerPublicParams;
|
||||
private final SignalServiceUrl[] signalServiceUrls;
|
||||
private final Map<Integer, SignalCdnUrl[]> signalCdnUrlMap;
|
||||
private final SignalContactDiscoveryUrl[] signalContactDiscoveryUrls;
|
||||
private final SignalKeyBackupServiceUrl[] signalKeyBackupServiceUrls;
|
||||
private final SignalStorageUrl[] signalStorageUrls;
|
||||
private final List<Interceptor> networkInterceptors;
|
||||
private final Optional<Dns> dns;
|
||||
private final byte[] zkGroupServerPublicParams;
|
||||
|
||||
public SignalServiceConfiguration(SignalServiceUrl[] signalServiceUrls,
|
||||
SignalCdnUrl[] signalCdnUrls,
|
||||
SignalCdnUrl[] signalCdn2Urls,
|
||||
Map<Integer, SignalCdnUrl[]> signalCdnUrlMap,
|
||||
SignalContactDiscoveryUrl[] signalContactDiscoveryUrls,
|
||||
SignalKeyBackupServiceUrl[] signalKeyBackupServiceUrls,
|
||||
SignalStorageUrl[] signalStorageUrls,
|
||||
|
@ -30,8 +29,7 @@ public final class SignalServiceConfiguration {
|
|||
byte[] zkGroupServerPublicParams)
|
||||
{
|
||||
this.signalServiceUrls = signalServiceUrls;
|
||||
this.signalCdnUrls = signalCdnUrls;
|
||||
this.signalCdn2Urls = signalCdn2Urls;
|
||||
this.signalCdnUrlMap = signalCdnUrlMap;
|
||||
this.signalContactDiscoveryUrls = signalContactDiscoveryUrls;
|
||||
this.signalKeyBackupServiceUrls = signalKeyBackupServiceUrls;
|
||||
this.signalStorageUrls = signalStorageUrls;
|
||||
|
@ -44,12 +42,8 @@ public final class SignalServiceConfiguration {
|
|||
return signalServiceUrls;
|
||||
}
|
||||
|
||||
public SignalCdnUrl[] getSignalCdnUrls() {
|
||||
return signalCdnUrls;
|
||||
}
|
||||
|
||||
public SignalCdnUrl[] getSignalCdn2Urls() {
|
||||
return signalCdn2Urls;
|
||||
public Map<Integer, SignalCdnUrl[]> getSignalCdnUrlMap() {
|
||||
return signalCdnUrlMap;
|
||||
}
|
||||
|
||||
public SignalContactDiscoveryUrl[] getSignalContactDiscoveryUrls() {
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredExcep
|
|||
import org.whispersystems.signalservice.api.push.exceptions.ConflictException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ContactManifestMismatchException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NoContentException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
||||
|
@ -62,6 +63,7 @@ import org.whispersystems.signalservice.api.storage.StorageAuthResponse;
|
|||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.api.util.Tls12SocketFactory;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalUrl;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest;
|
||||
|
@ -98,6 +100,7 @@ import java.security.KeyManagementException;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -191,17 +194,16 @@ public class PushServiceSocket {
|
|||
private long soTimeoutMillis = TimeUnit.SECONDS.toMillis(30);
|
||||
private final Set<Call> connections = new HashSet<>();
|
||||
|
||||
private final ServiceConnectionHolder[] serviceClients;
|
||||
private final ConnectionHolder[] cdnClients;
|
||||
private final ConnectionHolder[] cdn2Clients;
|
||||
private final ConnectionHolder[] contactDiscoveryClients;
|
||||
private final ConnectionHolder[] keyBackupServiceClients;
|
||||
private final ConnectionHolder[] storageClients;
|
||||
private final ServiceConnectionHolder[] serviceClients;
|
||||
private final Map<Integer, ConnectionHolder[]> cdnClientsMap;
|
||||
private final ConnectionHolder[] contactDiscoveryClients;
|
||||
private final ConnectionHolder[] keyBackupServiceClients;
|
||||
private final ConnectionHolder[] storageClients;
|
||||
|
||||
private final CredentialsProvider credentialsProvider;
|
||||
private final String signalAgent;
|
||||
private final SecureRandom random;
|
||||
private final ClientZkProfileOperations clientZkProfileOperations;
|
||||
private final CredentialsProvider credentialsProvider;
|
||||
private final String signalAgent;
|
||||
private final SecureRandom random;
|
||||
private final ClientZkProfileOperations clientZkProfileOperations;
|
||||
|
||||
public PushServiceSocket(SignalServiceConfiguration configuration,
|
||||
CredentialsProvider credentialsProvider,
|
||||
|
@ -211,8 +213,7 @@ public class PushServiceSocket {
|
|||
this.credentialsProvider = credentialsProvider;
|
||||
this.signalAgent = signalAgent;
|
||||
this.serviceClients = createServiceConnectionHolders(configuration.getSignalServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
this.cdnClients = createConnectionHolders(configuration.getSignalCdnUrls(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
this.cdn2Clients = createConnectionHolders(configuration.getSignalCdn2Urls(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
this.cdnClientsMap = createCdnClientsMap(configuration.getSignalCdnUrlMap(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
this.contactDiscoveryClients = createConnectionHolders(configuration.getSignalContactDiscoveryUrls(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
this.keyBackupServiceClients = createConnectionHolders(configuration.getSignalKeyBackupServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
this.storageClients = createConnectionHolders(configuration.getSignalStorageUrls(), configuration.getNetworkInterceptors(), configuration.getDns());
|
||||
|
@ -517,8 +518,7 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
public void retrieveAttachment(int cdnNumber, SignalServiceAttachmentRemoteId cdnPath, File destination, long maxSizeBytes, ProgressListener listener)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException, MissingConfigurationException {
|
||||
final String path;
|
||||
if (cdnPath.getV2().isPresent()) {
|
||||
path = String.format(Locale.US, ATTACHMENT_ID_DOWNLOAD_PATH, cdnPath.getV2().get());
|
||||
|
@ -529,30 +529,35 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
public void retrieveSticker(File destination, byte[] packId, int stickerId)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException, MissingConfigurationException {
|
||||
String hexPackId = Hex.toStringCondensed(packId);
|
||||
downloadFromCdn(destination, 0, String.format(Locale.US, STICKER_PATH, hexPackId, stickerId), 1024 * 1024, null);
|
||||
}
|
||||
|
||||
public byte[] retrieveSticker(byte[] packId, int stickerId)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException {
|
||||
String hexPackId = Hex.toStringCondensed(packId);
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
downloadFromCdn(output, 0, 0, String.format(Locale.US, STICKER_PATH, hexPackId, stickerId), 1024 * 1024, null);
|
||||
try {
|
||||
downloadFromCdn(output, 0, 0, String.format(Locale.US, STICKER_PATH, hexPackId, stickerId), 1024 * 1024, null);
|
||||
} catch (MissingConfigurationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
public byte[] retrieveStickerManifest(byte[] packId)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException {
|
||||
String hexPackId = Hex.toStringCondensed(packId);
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
downloadFromCdn(output, 0, 0, String.format(STICKER_MANIFEST_PATH, hexPackId), 1024 * 1024, null);
|
||||
try {
|
||||
downloadFromCdn(output, 0, 0, String.format(STICKER_MANIFEST_PATH, hexPackId), 1024 * 1024, null);
|
||||
} catch (MissingConfigurationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
@ -615,9 +620,12 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
public void retrieveProfileAvatar(String path, File destination, long maxSizeBytes)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
downloadFromCdn(destination, 0, path, maxSizeBytes, null);
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException {
|
||||
try {
|
||||
downloadFromCdn(destination, 0, path, maxSizeBytes, null);
|
||||
} catch (MissingConfigurationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProfileName(String name) throws NonSuccessfulResponseCodeException, PushNetworkException {
|
||||
|
@ -646,7 +654,7 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
if (profileAvatar != null) {
|
||||
uploadToCdn(AVATAR_UPLOAD_PATH, formAttributes.getAcl(), formAttributes.getKey(),
|
||||
uploadToCdn0(AVATAR_UPLOAD_PATH, formAttributes.getAcl(), formAttributes.getKey(),
|
||||
formAttributes.getPolicy(), formAttributes.getAlgorithm(),
|
||||
formAttributes.getCredential(), formAttributes.getDate(),
|
||||
formAttributes.getSignature(), profileAvatar.getData(),
|
||||
|
@ -682,7 +690,7 @@ public class PushServiceSocket {
|
|||
throw new NonSuccessfulResponseCodeException("Unable to parse entity");
|
||||
}
|
||||
|
||||
uploadToCdn(AVATAR_UPLOAD_PATH, formAttributes.getAcl(), formAttributes.getKey(),
|
||||
uploadToCdn0(AVATAR_UPLOAD_PATH, formAttributes.getAcl(), formAttributes.getKey(),
|
||||
formAttributes.getPolicy(), formAttributes.getAlgorithm(),
|
||||
formAttributes.getCredential(), formAttributes.getDate(),
|
||||
formAttributes.getSignature(), profileAvatar.getData(),
|
||||
|
@ -896,7 +904,7 @@ public class PushServiceSocket {
|
|||
public byte[] uploadGroupV2Avatar(byte[] avatarCipherText, AvatarUploadAttributes uploadAttributes)
|
||||
throws IOException
|
||||
{
|
||||
return uploadToCdn(AVATAR_UPLOAD_PATH, uploadAttributes.getAcl(), uploadAttributes.getKey(),
|
||||
return uploadToCdn0(AVATAR_UPLOAD_PATH, uploadAttributes.getAcl(), uploadAttributes.getKey(),
|
||||
uploadAttributes.getPolicy(), uploadAttributes.getAlgorithm(),
|
||||
uploadAttributes.getCredential(), uploadAttributes.getDate(),
|
||||
uploadAttributes.getSignature(),
|
||||
|
@ -910,7 +918,7 @@ public class PushServiceSocket {
|
|||
throws PushNetworkException, NonSuccessfulResponseCodeException
|
||||
{
|
||||
long id = Long.parseLong(uploadAttributes.getAttachmentId());
|
||||
byte[] digest = uploadToCdn(ATTACHMENT_UPLOAD_PATH, uploadAttributes.getAcl(), uploadAttributes.getKey(),
|
||||
byte[] digest = uploadToCdn0(ATTACHMENT_UPLOAD_PATH, uploadAttributes.getAcl(), uploadAttributes.getKey(),
|
||||
uploadAttributes.getPolicy(), uploadAttributes.getAlgorithm(),
|
||||
uploadAttributes.getCredential(), uploadAttributes.getDate(),
|
||||
uploadAttributes.getSignature(), attachment.getData(),
|
||||
|
@ -933,8 +941,7 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
private void downloadFromCdn(File destination, int cdnNumber, String path, long maxSizeBytes, ProgressListener listener)
|
||||
throws PushNetworkException, NonSuccessfulResponseCodeException
|
||||
{
|
||||
throws PushNetworkException, NonSuccessfulResponseCodeException, MissingConfigurationException {
|
||||
try (FileOutputStream outputStream = new FileOutputStream(destination, true)) {
|
||||
downloadFromCdn(outputStream, destination.length(), cdnNumber, path, maxSizeBytes, listener);
|
||||
} catch (IOException e) {
|
||||
|
@ -943,14 +950,17 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
private void downloadFromCdn(OutputStream outputStream, long offset, int cdnNumber, String path, long maxSizeBytes, ProgressListener listener)
|
||||
throws PushNetworkException, NonSuccessfulResponseCodeException
|
||||
{
|
||||
ConnectionHolder connectionHolder = getRandom(cdnNumber == 2 ? cdn2Clients : cdnClients, random);
|
||||
OkHttpClient okHttpClient = connectionHolder.getClient()
|
||||
.newBuilder()
|
||||
.connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
.readTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
throws PushNetworkException, NonSuccessfulResponseCodeException, MissingConfigurationException {
|
||||
ConnectionHolder[] cdnNumberClients = cdnClientsMap.get(cdnNumber);
|
||||
if (cdnNumberClients == null) {
|
||||
throw new MissingConfigurationException("Attempted to download from unsupported CDN number: " + cdnNumber + ", Our configuration supports: " + cdnClientsMap.keySet());
|
||||
}
|
||||
ConnectionHolder connectionHolder = getRandom(cdnNumberClients, random);
|
||||
OkHttpClient okHttpClient = connectionHolder.getClient()
|
||||
.newBuilder()
|
||||
.connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
.readTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
|
||||
Request.Builder request = new Request.Builder().url(connectionHolder.getUrl() + "/" + path).get();
|
||||
|
||||
|
@ -1012,14 +1022,14 @@ public class PushServiceSocket {
|
|||
throw new NonSuccessfulResponseCodeException("Response: " + response);
|
||||
}
|
||||
|
||||
private byte[] uploadToCdn(String path, String acl, String key, String policy, String algorithm,
|
||||
String credential, String date, String signature,
|
||||
InputStream data, String contentType, long length,
|
||||
OutputStreamFactory outputStreamFactory, ProgressListener progressListener,
|
||||
CancelationSignal cancelationSignal)
|
||||
private byte[] uploadToCdn0(String path, String acl, String key, String policy, String algorithm,
|
||||
String credential, String date, String signature,
|
||||
InputStream data, String contentType, long length,
|
||||
OutputStreamFactory outputStreamFactory, ProgressListener progressListener,
|
||||
CancelationSignal cancelationSignal)
|
||||
throws PushNetworkException, NonSuccessfulResponseCodeException
|
||||
{
|
||||
ConnectionHolder connectionHolder = getRandom(cdnClients, random);
|
||||
ConnectionHolder connectionHolder = getRandom(cdnClientsMap.get(0), random);
|
||||
OkHttpClient okHttpClient = connectionHolder.getClient()
|
||||
.newBuilder()
|
||||
.connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
|
@ -1074,7 +1084,7 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
private String getResumableUploadUrl(String signedUrl, Map<String, String> headers) throws IOException {
|
||||
ConnectionHolder connectionHolder = getRandom(cdn2Clients, random);
|
||||
ConnectionHolder connectionHolder = getRandom(cdnClientsMap.get(2), random);
|
||||
OkHttpClient okHttpClient = connectionHolder.getClient()
|
||||
.newBuilder()
|
||||
.connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
|
@ -1135,7 +1145,7 @@ public class PushServiceSocket {
|
|||
}
|
||||
|
||||
private byte[] uploadToCdn2(String resumableUrl, InputStream data, String contentType, long length, OutputStreamFactory outputStreamFactory, ProgressListener progressListener, CancelationSignal cancelationSignal) throws IOException {
|
||||
ConnectionHolder connectionHolder = getRandom(cdn2Clients, random);
|
||||
ConnectionHolder connectionHolder = getRandom(cdnClientsMap.get(2), random);
|
||||
OkHttpClient okHttpClient = connectionHolder.getClient()
|
||||
.newBuilder()
|
||||
.connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS)
|
||||
|
@ -1531,7 +1541,25 @@ public class PushServiceSocket {
|
|||
return serviceConnectionHolders.toArray(new ServiceConnectionHolder[0]);
|
||||
}
|
||||
|
||||
private ConnectionHolder[] createConnectionHolders(SignalUrl[] urls, List<Interceptor> interceptors, Optional<Dns> dns) {
|
||||
private static Map<Integer, ConnectionHolder[]> createCdnClientsMap(final Map<Integer, SignalCdnUrl[]> signalCdnUrlMap,
|
||||
final List<Interceptor> interceptors,
|
||||
final Optional<Dns> dns) {
|
||||
validateConfiguration(signalCdnUrlMap);
|
||||
final Map<Integer, ConnectionHolder[]> result = new HashMap<>();
|
||||
for (Map.Entry<Integer, SignalCdnUrl[]> entry : signalCdnUrlMap.entrySet()) {
|
||||
result.put(entry.getKey(),
|
||||
createConnectionHolders(entry.getValue(), interceptors, dns));
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
private static void validateConfiguration(Map<Integer, SignalCdnUrl[]> signalCdnUrlMap) {
|
||||
if (!signalCdnUrlMap.containsKey(0) || !signalCdnUrlMap.containsKey(2)) {
|
||||
throw new AssertionError("Configuration used to create PushServiceSocket must support CDN 0 and CDN 2");
|
||||
}
|
||||
}
|
||||
|
||||
private static ConnectionHolder[] createConnectionHolders(SignalUrl[] urls, List<Interceptor> interceptors, Optional<Dns> dns) {
|
||||
List<ConnectionHolder> connectionHolders = new LinkedList<>();
|
||||
|
||||
for (SignalUrl url : urls) {
|
||||
|
@ -1541,7 +1569,7 @@ public class PushServiceSocket {
|
|||
return connectionHolders.toArray(new ConnectionHolder[0]);
|
||||
}
|
||||
|
||||
private OkHttpClient createConnectionClient(SignalUrl url, List<Interceptor> interceptors, Optional<Dns> dns) {
|
||||
private static OkHttpClient createConnectionClient(SignalUrl url, List<Interceptor> interceptors, Optional<Dns> dns) {
|
||||
try {
|
||||
TrustManager[] trustManagers = BlacklistingTrustManager.createFor(url.getTrustStore());
|
||||
|
||||
|
|
|
@ -4,33 +4,27 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
|||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext;
|
||||
|
||||
/**
|
||||
* Exception that indicates that the data message has a higher required protocol version than the
|
||||
* current client is capable of interpreting.
|
||||
* Exception that indicates that the data message contains something that is not supported by this
|
||||
* version of the application. Subclasses provide more specific information about what data was
|
||||
* found that is not supported.
|
||||
*/
|
||||
public class UnsupportedDataMessageException extends Exception {
|
||||
public abstract class UnsupportedDataMessageException extends Exception {
|
||||
|
||||
private final int requiredVersion;
|
||||
private final String sender;
|
||||
private final int senderDevice;
|
||||
private final Optional<SignalServiceGroupContext> group;
|
||||
|
||||
public UnsupportedDataMessageException(int currentVersion,
|
||||
int requiredVersion,
|
||||
String sender,
|
||||
int senderDevice,
|
||||
Optional<SignalServiceGroupContext> group)
|
||||
protected UnsupportedDataMessageException(String message,
|
||||
String sender,
|
||||
int senderDevice,
|
||||
Optional<SignalServiceGroupContext> group)
|
||||
{
|
||||
super("Required version: " + requiredVersion + ", Our version: " + currentVersion);
|
||||
this.requiredVersion = requiredVersion;
|
||||
super(message);
|
||||
this.sender = sender;
|
||||
this.senderDevice = senderDevice;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public int getRequiredVersion() {
|
||||
return requiredVersion;
|
||||
}
|
||||
|
||||
public String getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext;
|
||||
|
||||
/**
|
||||
* Exception that indicates that the data message has a higher required protocol version than the
|
||||
* current client is capable of interpreting.
|
||||
*/
|
||||
public final class UnsupportedDataMessageProtocolVersionException extends UnsupportedDataMessageException {
|
||||
private final int requiredVersion;
|
||||
|
||||
public UnsupportedDataMessageProtocolVersionException(int currentVersion,
|
||||
int requiredVersion,
|
||||
String sender,
|
||||
int senderDevice,
|
||||
Optional<SignalServiceGroupContext> group) {
|
||||
super("Required version: " + requiredVersion + ", Our version: " + currentVersion, sender, senderDevice, group);
|
||||
this.requiredVersion = requiredVersion;
|
||||
}
|
||||
|
||||
public int getRequiredVersion() {
|
||||
return requiredVersion;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue