@onekeyfe/react-native-sni-connect 3.0.87 → 3.0.89
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.
|
@@ -190,10 +190,7 @@ final class SniConnectClient {
|
|
|
190
190
|
private let tasksQueue = DispatchQueue(label: "com.onekey.sni.connect.tasks", attributes: .concurrent)
|
|
191
191
|
private let requestLimiter = SniConnectRequestLimiter.shared
|
|
192
192
|
|
|
193
|
-
private
|
|
194
|
-
let hostname: String
|
|
195
|
-
let ip: String
|
|
196
|
-
}
|
|
193
|
+
private typealias SessionKey = SniConnectEndpointKey
|
|
197
194
|
|
|
198
195
|
private struct SessionLease {
|
|
199
196
|
let session: URLSession
|
|
@@ -404,15 +401,15 @@ final class SniConnectClient {
|
|
|
404
401
|
}
|
|
405
402
|
}
|
|
406
403
|
|
|
407
|
-
private static func makeURLSession(
|
|
404
|
+
private static func makeURLSession(hostname: String, ip: String) throws -> ManagedSession {
|
|
408
405
|
let resources = try SniConnectPinnedTransport.makeResources(
|
|
409
|
-
hostname:
|
|
410
|
-
ip:
|
|
406
|
+
hostname: hostname,
|
|
407
|
+
ip: ip
|
|
411
408
|
)
|
|
412
409
|
SniConnectLog.info(SniConnectLog.event("sni_transport_config", [
|
|
413
|
-
("hostname",
|
|
414
|
-
("ipHash", SniConnectLog.shortHash(
|
|
415
|
-
("ipFamily", SniConnectLog.ipFamily(
|
|
410
|
+
("hostname", hostname),
|
|
411
|
+
("ipHash", SniConnectLog.shortHash(ip)),
|
|
412
|
+
("ipFamily", SniConnectLog.ipFamily(ip)),
|
|
416
413
|
("proxyMode", "no_proxy"),
|
|
417
414
|
("pinnedResolver", true),
|
|
418
415
|
("protocol", "http1"),
|
|
@@ -430,7 +427,7 @@ final class SniConnectClient {
|
|
|
430
427
|
}
|
|
431
428
|
|
|
432
429
|
private func sessionLease(for config: RequestConfig) async throws -> SessionLease {
|
|
433
|
-
let key = SessionKey(hostname: config.hostname
|
|
430
|
+
let key = SessionKey(hostname: config.hostname, ip: config.ip)
|
|
434
431
|
while true {
|
|
435
432
|
let acquisition = try Self.sessionsQueue.sync { () throws -> SessionAcquisition in
|
|
436
433
|
Self.pendingResolverSlots.removeAll { $0.isReleased }
|
|
@@ -448,7 +445,7 @@ final class SniConnectClient {
|
|
|
448
445
|
return .waitForResolverSlots(pendingResolverSlots)
|
|
449
446
|
}
|
|
450
447
|
|
|
451
|
-
let managedSession = try Self.makeURLSession(
|
|
448
|
+
let managedSession = try Self.makeURLSession(hostname: key.hostname, ip: config.ip)
|
|
452
449
|
Self.sessionCache[key] = managedSession
|
|
453
450
|
Self.markSessionUsed(key)
|
|
454
451
|
return .ready(Self.retainSession(managedSession.session))
|
|
@@ -460,7 +457,7 @@ final class SniConnectClient {
|
|
|
460
457
|
case .waitForResolverSlots(let resolverLeases):
|
|
461
458
|
SniConnectLog.info(SniConnectLog.event("sni_resolver_slot_wait", [
|
|
462
459
|
("hostname", key.hostname),
|
|
463
|
-
("ipHash", SniConnectLog.shortHash(
|
|
460
|
+
("ipHash", SniConnectLog.shortHash(config.ip)),
|
|
464
461
|
("waitCount", resolverLeases.count),
|
|
465
462
|
]))
|
|
466
463
|
for resolverLease in resolverLeases {
|
|
@@ -511,7 +508,7 @@ final class SniConnectClient {
|
|
|
511
508
|
}
|
|
512
509
|
SniConnectLog.info(SniConnectLog.event("sni_cache_evict", [
|
|
513
510
|
("hostname", evictedKey.hostname),
|
|
514
|
-
("ipHash", SniConnectLog.shortHash(evictedKey.
|
|
511
|
+
("ipHash", SniConnectLog.shortHash(evictedKey.canonicalIP)),
|
|
515
512
|
("cacheSize", sessionCache.count),
|
|
516
513
|
("limit", Self.maxCachedSessions),
|
|
517
514
|
("reason", forPendingInsert ? "max_cached_sessions_pending_insert" : "max_cached_sessions"),
|
package/ios/SniConnectCore.swift
CHANGED
|
@@ -47,6 +47,16 @@ struct SniConnectResolverConfig: Equatable {
|
|
|
47
47
|
let ip: String
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
struct SniConnectEndpointKey: Hashable {
|
|
51
|
+
let hostname: String
|
|
52
|
+
let canonicalIP: String
|
|
53
|
+
|
|
54
|
+
init(hostname: String, ip: String) {
|
|
55
|
+
self.hostname = hostname.lowercased()
|
|
56
|
+
canonicalIP = SniConnectValidation.canonicalIPKey(ip)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
enum SniConnectCoreError: Error {
|
|
51
61
|
case resourceLimit(String)
|
|
52
62
|
}
|
|
@@ -55,9 +65,9 @@ final class SniConnectPinnedResolverRegistry {
|
|
|
55
65
|
static let defaultMaxEntries = 32
|
|
56
66
|
|
|
57
67
|
private let maxEntries: Int
|
|
58
|
-
private var classesByKey: [
|
|
68
|
+
private var classesByKey: [SniConnectEndpointKey: AnyClass] = [:]
|
|
59
69
|
private var configsByClassName: [String: SniConnectResolverConfig] = [:]
|
|
60
|
-
private var referenceCountsByKey: [
|
|
70
|
+
private var referenceCountsByKey: [SniConnectEndpointKey: Int] = [:]
|
|
61
71
|
private var reusableClasses: [AnyClass] = []
|
|
62
72
|
private var allocatedClassNames: Set<String> = []
|
|
63
73
|
|
|
@@ -78,8 +88,7 @@ final class SniConnectPinnedResolverRegistry {
|
|
|
78
88
|
ip: String,
|
|
79
89
|
allocateClass: () -> AnyClass
|
|
80
90
|
) throws -> AnyClass {
|
|
81
|
-
let
|
|
82
|
-
let key = Self.key(hostname: normalizedHost, ip: ip)
|
|
91
|
+
let key = SniConnectEndpointKey(hostname: hostname, ip: ip)
|
|
83
92
|
if let resolverClass = classesByKey[key] {
|
|
84
93
|
referenceCountsByKey[key, default: 0] += 1
|
|
85
94
|
return resolverClass
|
|
@@ -93,7 +102,7 @@ final class SniConnectPinnedResolverRegistry {
|
|
|
93
102
|
let className = NSStringFromClass(resolverClass)
|
|
94
103
|
allocatedClassNames.insert(className)
|
|
95
104
|
classesByKey[key] = resolverClass
|
|
96
|
-
configsByClassName[className] = SniConnectResolverConfig(hostname:
|
|
105
|
+
configsByClassName[className] = SniConnectResolverConfig(hostname: key.hostname, ip: ip)
|
|
97
106
|
referenceCountsByKey[key] = 1
|
|
98
107
|
return resolverClass
|
|
99
108
|
}
|
|
@@ -114,7 +123,7 @@ final class SniConnectPinnedResolverRegistry {
|
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
func release(hostname: String, ip: String) {
|
|
117
|
-
let key =
|
|
126
|
+
let key = SniConnectEndpointKey(hostname: hostname, ip: ip)
|
|
118
127
|
guard let referenceCount = referenceCountsByKey[key] else {
|
|
119
128
|
return
|
|
120
129
|
}
|
|
@@ -137,10 +146,6 @@ final class SniConnectPinnedResolverRegistry {
|
|
|
137
146
|
configsByClassName.removeAll()
|
|
138
147
|
referenceCountsByKey.removeAll()
|
|
139
148
|
}
|
|
140
|
-
|
|
141
|
-
private static func key(hostname: String, ip: String) -> String {
|
|
142
|
-
return "\(hostname)|\(ip)"
|
|
143
|
-
}
|
|
144
149
|
}
|
|
145
150
|
|
|
146
151
|
enum SniConnectResponseText {
|
|
@@ -450,6 +450,36 @@ final class SniConnectValidationTests: XCTestCase {
|
|
|
450
450
|
XCTAssertEqual(registry.resolve(domain: "example.net", resolverClass: reused), "93.184.216.36")
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
func testEndpointCachesReuseEquivalentIPv6Spellings() throws {
|
|
454
|
+
final class ResolverA: NSObject {}
|
|
455
|
+
final class ResolverB: NSObject {}
|
|
456
|
+
let registry = SniConnectPinnedResolverRegistry(maxEntries: 2)
|
|
457
|
+
let compressedIP = "2606:4700:4700::1111"
|
|
458
|
+
let expandedIP = "2606:4700:4700:0:0:0:0:1111"
|
|
459
|
+
|
|
460
|
+
XCTAssertEqual(
|
|
461
|
+
SniConnectEndpointKey(hostname: "Example.com", ip: compressedIP),
|
|
462
|
+
SniConnectEndpointKey(hostname: "example.com", ip: expandedIP)
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
let first: AnyClass = try registry.resolverClass(hostname: "Example.com", ip: compressedIP) {
|
|
466
|
+
ResolverA.self
|
|
467
|
+
}
|
|
468
|
+
let same: AnyClass = try registry.resolverClass(hostname: "example.com", ip: expandedIP) {
|
|
469
|
+
XCTFail("Equivalent IPv6 spellings must reuse the resolver entry")
|
|
470
|
+
return ResolverB.self
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
XCTAssertTrue(first === same)
|
|
474
|
+
XCTAssertEqual(registry.entryCount, 1)
|
|
475
|
+
XCTAssertEqual(registry.allocatedClassCount, 1)
|
|
476
|
+
|
|
477
|
+
registry.release(hostname: "example.com", ip: expandedIP)
|
|
478
|
+
XCTAssertEqual(registry.entryCount, 1)
|
|
479
|
+
registry.release(hostname: "example.com", ip: compressedIP)
|
|
480
|
+
XCTAssertEqual(registry.entryCount, 0)
|
|
481
|
+
}
|
|
482
|
+
|
|
453
483
|
func testResponseTextDecodePreservesOriginalJsonText() throws {
|
|
454
484
|
let json = "{ \"b\": 1, \"a\": [true, null] }\n"
|
|
455
485
|
XCTAssertEqual(SniConnectResponseText.decode(Data(json.utf8)), json)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-sni-connect",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.89",
|
|
4
4
|
"description": "A React Native library for SNI-based HTTP requests with DNS caching and request management",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"@eslint/compat": "^1.3.2",
|
|
65
65
|
"@eslint/eslintrc": "^3.3.1",
|
|
66
66
|
"@eslint/js": "^9.35.0",
|
|
67
|
-
"@react-native/babel-preset": "0.
|
|
68
|
-
"@react-native/eslint-config": "0.
|
|
67
|
+
"@react-native/babel-preset": "0.86.2",
|
|
68
|
+
"@react-native/eslint-config": "0.86.2",
|
|
69
69
|
"@release-it/conventional-changelog": "^10.0.1",
|
|
70
70
|
"@types/jest": "^29.5.14",
|
|
71
71
|
"@types/react": "^19.2.0",
|
|
@@ -77,8 +77,8 @@
|
|
|
77
77
|
"jest": "^29.7.0",
|
|
78
78
|
"lefthook": "^2.0.3",
|
|
79
79
|
"prettier": "^2.8.8",
|
|
80
|
-
"react": "19.2.
|
|
81
|
-
"react-native": "patch:react-native@npm%3A0.
|
|
80
|
+
"react": "19.2.3",
|
|
81
|
+
"react-native": "patch:react-native@npm%3A0.86.2#~/.yarn/patches/react-native-npm-0.86.2-c9d546616f.patch",
|
|
82
82
|
"react-native-builder-bob": "^0.40.17",
|
|
83
83
|
"release-it": "^19.0.4",
|
|
84
84
|
"turbo": "^2.5.6",
|