@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.
Files changed (38) hide show
  1. package/ReactNativeRangeDownloader.podspec +1 -1
  2. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRules.kt +12 -5
  3. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactOrphanSweep.kt +111 -0
  4. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactStore.kt +185 -189
  5. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/ReactNativeRangeDownloader.kt +16 -20
  6. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveRulesTest.kt +39 -0
  7. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactDeadlineTest.kt +26 -0
  8. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactOrphanSweepTest.kt +107 -0
  9. package/ios/FirmwareArtifactStore.swift +662 -408
  10. package/ios/RangeDownloadLogic.swift +297 -0
  11. package/ios/ReactNativeRangeDownloader.swift +42 -471
  12. package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts +3 -7
  13. package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts.map +1 -1
  14. package/nitrogen/generated/android/c++/JFirmwareArchiveMaterializeParams.hpp +7 -6
  15. package/nitrogen/generated/android/c++/JFirmwareArtifactDownloadParams.hpp +7 -7
  16. package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.cpp +0 -19
  17. package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.hpp +0 -1
  18. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArchiveMaterializeParams.kt +2 -2
  19. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactDownloadParams.kt +3 -3
  20. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/HybridReactNativeRangeDownloaderSpec.kt +0 -4
  21. package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Bridge.hpp +15 -0
  22. package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Umbrella.hpp +0 -3
  23. package/nitrogen/generated/ios/c++/HybridReactNativeRangeDownloaderSpecSwift.hpp +0 -11
  24. package/nitrogen/generated/ios/swift/FirmwareArchiveMaterializeParams.swift +32 -13
  25. package/nitrogen/generated/ios/swift/FirmwareArtifactDownloadParams.swift +39 -8
  26. package/nitrogen/generated/ios/swift/HybridReactNativeRangeDownloaderSpec.swift +0 -1
  27. package/nitrogen/generated/ios/swift/HybridReactNativeRangeDownloaderSpec_cxx.swift +0 -19
  28. package/nitrogen/generated/shared/c++/FirmwareArchiveMaterializeParams.hpp +6 -5
  29. package/nitrogen/generated/shared/c++/FirmwareArtifactDownloadParams.hpp +9 -9
  30. package/nitrogen/generated/shared/c++/HybridReactNativeRangeDownloaderSpec.cpp +0 -1
  31. package/nitrogen/generated/shared/c++/HybridReactNativeRangeDownloaderSpec.hpp +0 -4
  32. package/package.json +2 -2
  33. package/src/ReactNativeRangeDownloader.nitro.ts +4 -11
  34. package/ios/FirmwareBackgroundSessionEventRouter.swift +0 -17
  35. package/nitrogen/generated/android/c++/JFirmwareArtifactLeaseReconcileParams.hpp +0 -76
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/FirmwareArtifactLeaseReconcileParams.kt +0 -38
  37. package/nitrogen/generated/ios/swift/FirmwareArtifactLeaseReconcileParams.swift +0 -48
  38. 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["version"]
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"',
@@ -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.associateBy { it.entryName }
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
- ?: error("Firmware archive contains an unexpected entry")
93
- val expectedSize = requirement.expectedSize.toLong()
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
+ }