Introduce SignalNetwork, share PushServiceSocket.

This commit is contained in:
Greyson Parrelli
2024-09-03 15:20:31 -04:00
committed by Cody Henthorne
parent 4e35906680
commit 00d20a1917
18 changed files with 190 additions and 268 deletions

View File

@@ -56,6 +56,7 @@ import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.net.SignalNetwork
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.toMillis
import org.whispersystems.signalservice.api.NetworkResult
@@ -471,33 +472,30 @@ object BackupRepository {
}
fun listRemoteMediaObjects(limit: Int, cursor: String? = null): NetworkResult<ArchiveGetMediaItemsResponse> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getArchiveMediaItemsPage(backupKey, SignalStore.account.requireAci(), credential, limit, cursor)
SignalNetwork.archive.getArchiveMediaItemsPage(backupKey, SignalStore.account.requireAci(), credential, limit, cursor)
}
}
fun getRemoteBackupUsedSpace(): NetworkResult<Long?> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
.map { it.usedSpace }
}
}
private fun getBackupTier(): NetworkResult<MessageBackupTier> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
private fun getBackupTier(aci: ACI): NetworkResult<MessageBackupTier> {
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.map { credential ->
val zkCredential = api.getZkCredential(backupKey, credential)
val zkCredential = SignalNetwork.archive.getZkCredential(backupKey, aci, credential)
if (zkCredential.backupLevel == BackupLevel.MEDIA) {
MessageBackupTier.PAID
} else {
@@ -510,17 +508,16 @@ object BackupRepository {
* Returns an object with details about the remote backup state.
*/
fun getRemoteBackupState(): NetworkResult<BackupMetadata> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
.map { it to credential }
}
.then { pair ->
val (info, credential) = pair
api.debugGetUploadedMediaItemMetadata(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.debugGetUploadedMediaItemMetadata(backupKey, SignalStore.account.requireAci(), credential)
.also { Log.i(TAG, "MediaItemMetadataResult: $it") }
.map { mediaObjects ->
BackupMetadata(
@@ -537,34 +534,32 @@ object BackupRepository {
* @return True if successful, otherwise false.
*/
fun uploadBackupFile(backupStream: InputStream, backupStreamLength: Long): Boolean {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getMessageBackupUploadForm(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.getMessageBackupUploadForm(backupKey, SignalStore.account.requireAci(), credential)
.also { Log.i(TAG, "UploadFormResult: $it") }
}
.then { form ->
api.getBackupResumableUploadUrl(form)
SignalNetwork.archive.getBackupResumableUploadUrl(form)
.also { Log.i(TAG, "ResumableUploadUrlResult: $it") }
.map { form to it }
}
.then { formAndUploadUrl ->
val (form, resumableUploadUrl) = formAndUploadUrl
api.uploadBackupFile(form, resumableUploadUrl, backupStream, backupStreamLength)
SignalNetwork.archive.uploadBackupFile(form, resumableUploadUrl, backupStream, backupStreamLength)
.also { Log.i(TAG, "UploadBackupFileResult: $it") }
}
.also { Log.i(TAG, "OverallResult: $it") } is NetworkResult.Success
}
fun downloadBackupFile(destination: File, listener: ProgressListener? = null): Boolean {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
}
.then { info -> getCdnReadCredentials(info.cdn ?: Cdn.CDN_3.cdnNumber).map { it.headers to info } }
.map { pair ->
@@ -575,12 +570,11 @@ object BackupRepository {
}
fun getBackupFileLastModified(): NetworkResult<ZonedDateTime?> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential)
}
.then { info -> getCdnReadCredentials(info.cdn ?: Cdn.CDN_3.cdnNumber).map { it.headers to info } }
.then { pair ->
@@ -596,12 +590,11 @@ object BackupRepository {
* Returns an object with details about the remote backup state.
*/
fun debugGetArchivedMediaState(): NetworkResult<List<ArchiveGetMediaItemsResponse.StoredMediaObject>> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.debugGetUploadedMediaItemMetadata(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.debugGetUploadedMediaItemMetadata(backupKey, SignalStore.account.requireAci(), credential)
}
}
@@ -609,26 +602,24 @@ object BackupRepository {
* Retrieves an upload spec that can be used to upload attachment media.
*/
fun getMediaUploadSpec(secretKey: ByteArray? = null): NetworkResult<ResumableUploadSpec> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getMediaUploadForm(backupKey, SignalStore.account.requireAci(), credential)
SignalNetwork.archive.getMediaUploadForm(backupKey, SignalStore.account.requireAci(), credential)
}
.then { form ->
api.getResumableUploadSpec(form, secretKey)
SignalNetwork.archive.getResumableUploadSpec(form, secretKey)
}
}
fun archiveThumbnail(thumbnailAttachment: Attachment, parentAttachment: DatabaseAttachment): NetworkResult<ArchiveMediaResponse> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
val request = thumbnailAttachment.toArchiveMediaRequest(parentAttachment.getThumbnailMediaName(), backupKey)
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.archiveAttachmentMedia(
SignalNetwork.archive.archiveAttachmentMedia(
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
serviceCredential = credential,
@@ -638,14 +629,13 @@ object BackupRepository {
}
fun archiveMedia(attachment: DatabaseAttachment): NetworkResult<Unit> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
val mediaName = attachment.getMediaName()
val request = attachment.toArchiveMediaRequest(mediaName, backupKey)
api
SignalNetwork.archive
.archiveAttachmentMedia(
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
@@ -662,7 +652,6 @@ object BackupRepository {
}
fun archiveMedia(databaseAttachments: List<DatabaseAttachment>): NetworkResult<BatchArchiveMediaResult> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
@@ -679,7 +668,7 @@ object BackupRepository {
attachmentIdToMediaName[it.attachmentId] = mediaName.name
}
api
SignalNetwork.archive
.archiveAttachmentMedia(
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
@@ -703,7 +692,6 @@ object BackupRepository {
}
fun deleteArchivedMedia(attachments: List<DatabaseAttachment>): NetworkResult<Unit> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
val mediaToDelete = attachments
@@ -722,7 +710,7 @@ object BackupRepository {
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.deleteArchivedMedia(
SignalNetwork.archive.deleteArchivedMedia(
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
serviceCredential = credential,
@@ -736,7 +724,6 @@ object BackupRepository {
}
fun deleteAbandonedMediaObjects(mediaObjects: Collection<ArchivedMediaObject>): NetworkResult<Unit> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
val mediaToDelete = mediaObjects
@@ -754,7 +741,7 @@ object BackupRepository {
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.deleteArchivedMedia(
SignalNetwork.archive.deleteArchivedMedia(
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
serviceCredential = credential,
@@ -765,7 +752,6 @@ object BackupRepository {
}
fun debugDeleteAllArchivedMedia(): NetworkResult<Unit> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return debugGetArchivedMediaState()
@@ -784,7 +770,7 @@ object BackupRepository {
} else {
getAuthCredential()
.then { credential ->
api.deleteArchivedMedia(
SignalNetwork.archive.deleteArchivedMedia(
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
serviceCredential = credential,
@@ -808,12 +794,11 @@ object BackupRepository {
return NetworkResult.Success(cached)
}
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getCdnReadCredentials(
SignalNetwork.archive.getCdnReadCredentials(
cdnNumber = cdnNumber,
backupKey = backupKey,
aci = SignalStore.account.requireAci(),
@@ -828,7 +813,7 @@ object BackupRepository {
.also { Log.i(TAG, "getCdnReadCredentialsResult: $it") }
}
fun restoreBackupTier(): MessageBackupTier? {
fun restoreBackupTier(aci: ACI): MessageBackupTier? {
// TODO: more complete error handling
try {
val lastModified = getBackupFileLastModified().successOrThrow()
@@ -841,7 +826,7 @@ object BackupRepository {
return null
}
SignalStore.backup.backupTier = try {
getBackupTier().successOrThrow()
getBackupTier(aci).successOrThrow()
} catch (e: Exception) {
Log.i(TAG, "Could not retrieve backup tier.", e)
null
@@ -867,12 +852,11 @@ object BackupRepository {
)
}
val api = AppDependencies.signalServiceAccountManager.archiveApi
val backupKey = SignalStore.svr.getOrCreateMasterKey().deriveBackupKey()
return initBackupAndFetchAuth(backupKey)
.then { credential ->
api.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential).map {
SignalNetwork.archive.getBackupInfo(backupKey, SignalStore.account.requireAci(), credential).map {
SignalStore.backup.usedBackupMediaSpace = it.usedSpace ?: 0L
BackupDirectories(it.backupDir!!, it.mediaDir!!)
}
@@ -941,15 +925,13 @@ object BackupRepository {
* Should be the basis of all backup operations.
*/
private fun initBackupAndFetchAuth(backupKey: BackupKey): NetworkResult<ArchiveServiceCredential> {
val api = AppDependencies.signalServiceAccountManager.archiveApi
return if (SignalStore.backup.backupsInitialized) {
getAuthCredential().runOnStatusCodeError(resetInitializedStateErrorAction)
} else {
return api
.triggerBackupIdReservation(backupKey)
return SignalNetwork.archive
.triggerBackupIdReservation(backupKey, SignalStore.account.requireAci())
.then { getAuthCredential() }
.then { credential -> api.setPublicKey(backupKey, SignalStore.account.requireAci(), credential).map { credential } }
.then { credential -> SignalNetwork.archive.setPublicKey(backupKey, SignalStore.account.requireAci(), credential).map { credential } }
.runIfSuccessful { SignalStore.backup.backupsInitialized = true }
.runOnStatusCodeError(resetInitializedStateErrorAction)
}
@@ -969,7 +951,7 @@ object BackupRepository {
Log.w(TAG, "No credentials found for today, need to fetch new ones! This shouldn't happen under normal circumstances. We should ensure the routine fetch is running properly.")
return AppDependencies.signalServiceAccountManager.archiveApi.getServiceCredentials(currentTime).map { result ->
return SignalNetwork.archive.getServiceCredentials(currentTime).map { result ->
SignalStore.backup.addCredentials(result.credentials.toList())
SignalStore.backup.clearCredentialsOlderThan(currentTime)
SignalStore.backup.credentialsByDay.getForCurrentTime(currentTime.milliseconds)!!