commit c1a01bf1695fd083cdadda4560eff5cf12aefaf5
parent 0f711b698ee14668bd29d337fe3e07962091a60c
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Sun, 28 May 2023 23:50:33 +0200
perf(cdndownloader): bolt http resolver
Diffstat:
2 files changed, 16 insertions(+), 65 deletions(-)
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt
@@ -377,7 +377,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
//download the message content
try {
- context.longToast("Querying $urlKey. It might take a while...")
+ context.shortToast("Querying $urlKey")
val downloadedMedia = MediaDownloaderHelper.downloadMediaFromKey(urlKey, canMergeOverlay(), isPreviewMode) {
EncryptionUtils.decryptInputStreamFromArroyo(it, contentType, messageReader)
}[MediaType.ORIGINAL] ?: throw Exception("Failed to download media for key $urlKey")
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/util/download/CdnDownloader.kt b/app/src/main/kotlin/me/rhunk/snapenhance/util/download/CdnDownloader.kt
@@ -1,64 +1,21 @@
package me.rhunk.snapenhance.util.download
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.joinAll
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
import me.rhunk.snapenhance.Constants
+import me.rhunk.snapenhance.util.protobuf.ProtoWriter
import java.io.InputStream
import java.net.URL
+import java.util.Base64
import javax.net.ssl.HttpsURLConnection
object CdnDownloader {
- const val BOLT_CDN_U = "https://bolt-gcdn.sc-cdn.net/u/"
- const val BOLT_CDN_X = "https://bolt-gcdn.sc-cdn.net/x/"
+ private const val BOLT_HTTP_RESOLVER_URL = "https://aws.api.snapchat.com/bolt-http"
const val CF_ST_CDN_D = "https://cf-st.sc-cdn.net/d/"
- const val CF_ST_CDN_F = "https://cf-st.sc-cdn.net/f/"
- const val CF_ST_CDN_H = "https://cf-st.sc-cdn.net/h/"
- const val CF_ST_CDN_G = "https://cf-st.sc-cdn.net/g/"
- const val CF_ST_CDN_O = "https://cf-st.sc-cdn.net/o/"
- const val CF_ST_CDN_I = "https://cf-st.sc-cdn.net/i/"
- const val CF_ST_CDN_J = "https://cf-st.sc-cdn.net/j/"
- const val CF_ST_CDN_C = "https://cf-st.sc-cdn.net/c/"
- const val CF_ST_CDN_M = "https://cf-st.sc-cdn.net/m/"
- const val CF_ST_CDN_A = "https://cf-st.sc-cdn.net/a/"
- const val CF_ST_CDN_AA = "https://cf-st.sc-cdn.net/aa/"
-
- private val keyCache: MutableMap<String, String> = mutableMapOf()
-
- fun downloadRemoteContent(
- key: String,
- vararg endpoints: String
- ): InputStream? = runBlocking {
- if (keyCache.containsKey(key)) {
- return@runBlocking queryRemoteContent(
- keyCache[key]!!
- )
- }
- val jobs = mutableListOf<Job>()
- var inputStream: InputStream? = null
-
- endpoints.forEach {
- launch(Dispatchers.IO) {
- val url = it + key
- queryRemoteContent(url)?.let { result ->
- keyCache[key] = url
- inputStream = result
- jobs.forEach { it.cancel() }
- }
- }.also { jobs.add(it) }
- }
- jobs.joinAll()
- inputStream
- }
-
private fun queryRemoteContent(url: String): InputStream? {
try {
val connection = URL(url).openConnection() as HttpsURLConnection
connection.requestMethod = "GET"
- connection.connectTimeout = 5000
+ connection.instanceFollowRedirects = true
connection.setRequestProperty("User-Agent", Constants.USER_AGENT)
return connection.inputStream
} catch (ignored: Throwable) {
@@ -66,23 +23,17 @@ object CdnDownloader {
return null
}
- //TODO: automatically detect the correct endpoint
fun downloadWithDefaultEndpoints(key: String): InputStream? {
- return downloadRemoteContent(
- key,
- CF_ST_CDN_F,
- CF_ST_CDN_H,
- BOLT_CDN_U,
- BOLT_CDN_X,
- CF_ST_CDN_O,
- CF_ST_CDN_I,
- CF_ST_CDN_C,
- CF_ST_CDN_J,
- CF_ST_CDN_M,
- CF_ST_CDN_A,
- CF_ST_CDN_AA,
- CF_ST_CDN_G,
- CF_ST_CDN_D
- )
+ val payload = ProtoWriter().apply {
+ write(2) {
+ writeString(2, key)
+ writeBuffer(3, byteArrayOf())
+ writeBuffer(3, byteArrayOf())
+ writeConstant(6, 6)
+ writeConstant(10, 4)
+ writeConstant(12, 1)
+ }
+ }.toByteArray()
+ return queryRemoteContent(BOLT_HTTP_RESOLVER_URL + "/resolve?co=" + Base64.getUrlEncoder().encodeToString(payload))
}
}