@onekeyfe/react-native-range-downloader 3.0.81-alpha.0 → 3.0.81-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReactNativeRangeDownloader.podspec +1 -1
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRules.kt +12 -5
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactOrphanSweep.kt +111 -0
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactStore.kt +185 -189
- package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/ReactNativeRangeDownloader.kt +16 -20
- package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRulesTest.kt +39 -0
- package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactDeadlineTest.kt +26 -0
- package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactOrphanSweepTest.kt +107 -0
- package/ios/FirmwareArtifactStore.swift +662 -408
- package/ios/RangeDownloadLogic.swift +297 -0
- package/ios/ReactNativeRangeDownloader.swift +42 -471
- package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts +3 -7
- package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JFirmwareArchiveMaterializeParams.hpp +7 -6
- package/nitrogen/generated/android/c++/JFirmwareArtifactDownloadParams.hpp +7 -7
- package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.cpp +0 -19
- package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.hpp +0 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveMaterializeParams.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactDownloadParams.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/HybridReactNativeRangeDownloaderSpec.kt +0 -4
- package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Bridge.hpp +15 -0
- package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Umbrella.hpp +0 -3
- package/nitrogen/generated/ios/c++/HybridReactNativeRangeDownloaderSpecSwift.hpp +0 -11
- package/nitrogen/generated/ios/swift/FirmwareArchiveMaterializeParams.swift +32 -13
- package/nitrogen/generated/ios/swift/FirmwareArtifactDownloadParams.swift +39 -8
- package/nitrogen/generated/ios/swift/HybridReactNativeRangeDownloaderSpec.swift +0 -1
- package/nitrogen/generated/ios/swift/HybridReactNativeRangeDownloaderSpec_cxx.swift +0 -19
- package/nitrogen/generated/shared/c++/FirmwareArchiveMaterializeParams.hpp +6 -5
- package/nitrogen/generated/shared/c++/FirmwareArtifactDownloadParams.hpp +9 -9
- package/nitrogen/generated/shared/c++/HybridReactNativeRangeDownloaderSpec.cpp +0 -1
- package/nitrogen/generated/shared/c++/HybridReactNativeRangeDownloaderSpec.hpp +0 -4
- package/package.json +2 -2
- package/src/ReactNativeRangeDownloader.nitro.ts +4 -11
- package/ios/FirmwareBackgroundSessionEventRouter.swift +0 -17
- package/nitrogen/generated/android/c++/JFirmwareArtifactLeaseReconcileParams.hpp +0 -76
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactLeaseReconcileParams.kt +0 -38
- package/nitrogen/generated/ios/swift/FirmwareArtifactLeaseReconcileParams.swift +0 -48
- package/nitrogen/generated/shared/c++/FirmwareArtifactLeaseReconcileParams.hpp +0 -76
|
@@ -23,7 +23,7 @@ Pod::Spec.new do |s|
|
|
|
23
23
|
s.dependency 'React-jsi'
|
|
24
24
|
s.dependency 'React-callinvoker'
|
|
25
25
|
s.dependency 'ReactNativeNativeLogger'
|
|
26
|
-
s.dependency 'SniConnect', package["
|
|
26
|
+
s.dependency 'SniConnect', package["peerDependencies"]["@onekeyfe/react-native-sni-connect"]
|
|
27
27
|
s.public_header_files = "ios/FirmwareArchiveMinizipBridge.h"
|
|
28
28
|
s.pod_target_xcconfig = {
|
|
29
29
|
'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SSZipArchive/SSZipArchive/minizip"',
|
package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRules.kt
CHANGED
|
@@ -78,24 +78,31 @@ internal object FirmwareArchiveRules {
|
|
|
78
78
|
|
|
79
79
|
fun validateCentralDirectory(
|
|
80
80
|
file: File,
|
|
81
|
-
requirements: List<FirmwareArchiveExpectedEntry
|
|
81
|
+
requirements: List<FirmwareArchiveExpectedEntry>?,
|
|
82
82
|
): List<FirmwareArchiveCentralEntry> {
|
|
83
83
|
val entries = scanCentralDirectory(file)
|
|
84
|
-
require(entries.size == requirements.size) {
|
|
84
|
+
require(requirements == null || entries.size == requirements.size) {
|
|
85
85
|
"Firmware archive has missing or extra entries"
|
|
86
86
|
}
|
|
87
|
-
val requirementsByName = requirements
|
|
87
|
+
val requirementsByName = requirements?.associateBy { it.entryName }.orEmpty()
|
|
88
88
|
val names = mutableSetOf<String>()
|
|
89
89
|
val canonicalNames = mutableSetOf<String>()
|
|
90
|
+
var totalSize = 0L
|
|
90
91
|
entries.forEach { entry ->
|
|
91
92
|
val requirement = requirementsByName[entry.name]
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
require(requirements == null || requirement != null) {
|
|
94
|
+
"Firmware archive contains an unexpected entry"
|
|
95
|
+
}
|
|
96
|
+
val expectedSize = requirement?.expectedSize?.toLong()
|
|
97
|
+
?: entry.uncompressedSize
|
|
98
|
+
totalSize = Math.addExact(totalSize, entry.uncompressedSize)
|
|
94
99
|
require(
|
|
95
100
|
names.add(entry.name) &&
|
|
96
101
|
validatePortableName(entry.name, canonicalNames) &&
|
|
97
102
|
entry.uncompressedSize == expectedSize &&
|
|
98
103
|
entry.uncompressedSize > 0 &&
|
|
104
|
+
entry.uncompressedSize <= MAX_ARCHIVE_ENTRY_BYTES &&
|
|
105
|
+
totalSize <= MAX_ARCHIVE_EXPANDED_BYTES &&
|
|
99
106
|
entry.compressedSize in 0..MAX_ARCHIVE_EXPANDED_BYTES &&
|
|
100
107
|
entry.uncompressedSize <=
|
|
101
108
|
Math.multiplyExact(entry.compressedSize.coerceAtLeast(1), 1000) &&
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
package com.margelo.nitro.reactnativerangedownloader
|
|
2
|
+
|
|
3
|
+
import java.io.File
|
|
4
|
+
|
|
5
|
+
internal const val FIRMWARE_ARTIFACT_FINAL_GRACE_MS = 24L * 60 * 60 * 1000
|
|
6
|
+
internal const val FIRMWARE_ARTIFACT_PARTIAL_GRACE_MS = 7L * 24 * 60 * 60 * 1000
|
|
7
|
+
internal const val FIRMWARE_ARTIFACT_SCRATCH_GRACE_MS =
|
|
8
|
+
FIRMWARE_ARTIFACT_PARTIAL_GRACE_MS
|
|
9
|
+
|
|
10
|
+
private val firmwareArtifactSha256Pattern = Regex("^[a-f0-9]{64}$")
|
|
11
|
+
private val firmwareArchiveScratchPattern = Regex(
|
|
12
|
+
"^archive-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-" +
|
|
13
|
+
"[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
|
14
|
+
)
|
|
15
|
+
private val firmwarePromoteScratchPattern = Regex(
|
|
16
|
+
"^\\.promote-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-" +
|
|
17
|
+
"[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
private fun File.isSymbolicLinkEntry(): Boolean = try {
|
|
21
|
+
val canonicalParent = parentFile?.canonicalFile
|
|
22
|
+
val entryFromCanonicalParent = canonicalParent?.let { File(it, name) } ?: this
|
|
23
|
+
entryFromCanonicalParent.canonicalFile != entryFromCanonicalParent.absoluteFile
|
|
24
|
+
} catch (_: Exception) {
|
|
25
|
+
true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private fun firmwareArtifactEntrySize(entry: File): Long {
|
|
29
|
+
if (entry.isSymbolicLinkEntry()) return 0
|
|
30
|
+
if (entry.isFile) return entry.length()
|
|
31
|
+
if (!entry.isDirectory) return 0
|
|
32
|
+
return entry.listFiles()?.sumOf(::firmwareArtifactEntrySize) ?: 0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private fun deleteFirmwareArtifactEntry(entry: File): Boolean {
|
|
36
|
+
if (entry.isSymbolicLinkEntry()) return entry.delete()
|
|
37
|
+
if (entry.isDirectory) {
|
|
38
|
+
val children = entry.listFiles() ?: return false
|
|
39
|
+
if (children.any { !deleteFirmwareArtifactEntry(it) }) return false
|
|
40
|
+
}
|
|
41
|
+
return entry.delete()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private fun firmwareArtifactEntryExceededGrace(
|
|
45
|
+
entry: File,
|
|
46
|
+
nowMs: Long,
|
|
47
|
+
graceMs: Long,
|
|
48
|
+
): Boolean {
|
|
49
|
+
val modifiedAt = entry.lastModified()
|
|
50
|
+
return modifiedAt > 0 && modifiedAt <= nowMs && nowMs - modifiedAt >= graceMs
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
internal fun sweepFirmwareArtifactOrphansAtRoot(
|
|
54
|
+
root: File,
|
|
55
|
+
retainedSha256: Set<String>,
|
|
56
|
+
activeSha256: Set<String>,
|
|
57
|
+
openPaths: Set<String>,
|
|
58
|
+
nowMs: Long = System.currentTimeMillis(),
|
|
59
|
+
): Pair<Int, Long> {
|
|
60
|
+
var deletedFiles = 0
|
|
61
|
+
var deletedBytes = 0L
|
|
62
|
+
root.listFiles()?.forEach { entry ->
|
|
63
|
+
val isSymbolicLink = entry.isSymbolicLinkEntry()
|
|
64
|
+
val isArchiveScratch = firmwareArchiveScratchPattern.matches(entry.name)
|
|
65
|
+
val isPromoteScratch = firmwarePromoteScratchPattern.matches(entry.name)
|
|
66
|
+
val isScratchCandidate = !isSymbolicLink &&
|
|
67
|
+
((isArchiveScratch && entry.isDirectory) ||
|
|
68
|
+
(isPromoteScratch && entry.isFile))
|
|
69
|
+
if (isScratchCandidate) {
|
|
70
|
+
if (
|
|
71
|
+
firmwareArtifactEntryExceededGrace(
|
|
72
|
+
entry,
|
|
73
|
+
nowMs,
|
|
74
|
+
FIRMWARE_ARTIFACT_SCRATCH_GRACE_MS,
|
|
75
|
+
)
|
|
76
|
+
) {
|
|
77
|
+
val size = firmwareArtifactEntrySize(entry)
|
|
78
|
+
if (deleteFirmwareArtifactEntry(entry)) {
|
|
79
|
+
deletedFiles += 1
|
|
80
|
+
deletedBytes += size
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return@forEach
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!entry.isFile || isSymbolicLink || entry.name.length < 64) return@forEach
|
|
87
|
+
val sha256 = entry.name.take(64)
|
|
88
|
+
if (
|
|
89
|
+
!firmwareArtifactSha256Pattern.matches(sha256) ||
|
|
90
|
+
sha256 in retainedSha256 ||
|
|
91
|
+
sha256 in activeSha256 ||
|
|
92
|
+
entry.absolutePath in openPaths
|
|
93
|
+
) {
|
|
94
|
+
return@forEach
|
|
95
|
+
}
|
|
96
|
+
val grace = if (entry.name.endsWith(".bin")) {
|
|
97
|
+
FIRMWARE_ARTIFACT_FINAL_GRACE_MS
|
|
98
|
+
} else if (entry.name.endsWith(".partial")) {
|
|
99
|
+
FIRMWARE_ARTIFACT_PARTIAL_GRACE_MS
|
|
100
|
+
} else {
|
|
101
|
+
return@forEach
|
|
102
|
+
}
|
|
103
|
+
if (!firmwareArtifactEntryExceededGrace(entry, nowMs, grace)) return@forEach
|
|
104
|
+
val size = entry.length()
|
|
105
|
+
if (entry.delete()) {
|
|
106
|
+
deletedFiles += 1
|
|
107
|
+
deletedBytes += size
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return deletedFiles to deletedBytes
|
|
111
|
+
}
|