react-native-zeroconf 0.15.1 → 0.15.2
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/ios/RNZeroconf/RNZeroconf.m +49 -10
- package/package.json +1 -1
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
@property (nonatomic, strong, readonly) NSMutableDictionary *resolvingServices;
|
|
15
15
|
@property (nonatomic, strong, readonly) NSMutableDictionary *publishedServices;
|
|
16
|
+
// Services already retried after a resolve timeout
|
|
17
|
+
@property (nonatomic, strong, readonly) NSMutableSet<NSString *> *retriedServices;
|
|
18
|
+
// Stopped browsers, kept alive until their asynchronous stop has been processed
|
|
19
|
+
@property (nonatomic, strong, readonly) NSMutableSet<NSNetServiceBrowser *> *stoppingBrowsers;
|
|
20
|
+
@property (nonatomic, assign) NSTimeInterval resolveTimeoutSeconds;
|
|
16
21
|
|
|
17
22
|
@end
|
|
18
23
|
|
|
@@ -25,13 +30,34 @@ RCT_EXPORT_MODULE()
|
|
|
25
30
|
RCT_EXPORT_METHOD(scan:(NSString *)type protocol:(NSString *)protocol domain:(NSString *)domain)
|
|
26
31
|
{
|
|
27
32
|
[self stop];
|
|
33
|
+
|
|
34
|
+
// A fresh browser for each scan, restarting a search on a browser that is still stopping can crash (#154)
|
|
35
|
+
self.browser = [[NSNetServiceBrowser alloc] init];
|
|
36
|
+
[self.browser setDelegate:self];
|
|
28
37
|
[self.browser searchForServicesOfType:[NSString stringWithFormat:@"_%@._%@.", type, protocol] inDomain:domain];
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
RCT_EXPORT_METHOD(stop)
|
|
32
41
|
{
|
|
33
|
-
|
|
42
|
+
NSNetServiceBrowser *browser = self.browser;
|
|
43
|
+
if (browser) {
|
|
44
|
+
self.browser = nil;
|
|
45
|
+
[self.stoppingBrowsers addObject:browser];
|
|
46
|
+
[browser stop];
|
|
47
|
+
|
|
48
|
+
// The stop completes asynchronously on the run loop, release the browser well after it
|
|
49
|
+
__weak RNZeroconf *weakSelf = self;
|
|
50
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
51
|
+
browser.delegate = nil;
|
|
52
|
+
[weakSelf.stoppingBrowsers removeObject:browser];
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
for (NSNetService *service in self.resolvingServices.allValues) {
|
|
56
|
+
service.delegate = nil;
|
|
57
|
+
[service stop];
|
|
58
|
+
}
|
|
34
59
|
[self.resolvingServices removeAllObjects];
|
|
60
|
+
[self.retriedServices removeAllObjects];
|
|
35
61
|
}
|
|
36
62
|
|
|
37
63
|
- (dispatch_queue_t)methodQueue
|
|
@@ -93,7 +119,7 @@ RCT_EXPORT_METHOD(unregisterService:(NSString *) serviceName)
|
|
|
93
119
|
self.resolvingServices[service.name] = service;
|
|
94
120
|
|
|
95
121
|
service.delegate = self;
|
|
96
|
-
[service resolveWithTimeout:
|
|
122
|
+
[service resolveWithTimeout:self.resolveTimeoutSeconds];
|
|
97
123
|
}
|
|
98
124
|
|
|
99
125
|
// When a service is removed.
|
|
@@ -127,7 +153,10 @@ RCT_EXPORT_METHOD(unregisterService:(NSString *) serviceName)
|
|
|
127
153
|
// When the search stops.
|
|
128
154
|
- (void) netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)browser
|
|
129
155
|
{
|
|
130
|
-
|
|
156
|
+
// A browser replaced by a newer scan stopping late shouldn't report the new scan as stopped
|
|
157
|
+
if (self.browser == nil || self.browser == browser) {
|
|
158
|
+
[self.bridge.eventDispatcher sendDeviceEventWithName:@"RNZeroconfStop" body:nil];
|
|
159
|
+
}
|
|
131
160
|
}
|
|
132
161
|
|
|
133
162
|
// When the search starts.
|
|
@@ -146,12 +175,22 @@ RCT_EXPORT_METHOD(unregisterService:(NSString *) serviceName)
|
|
|
146
175
|
|
|
147
176
|
sender.delegate = nil;
|
|
148
177
|
[self.resolvingServices removeObjectForKey:sender.name];
|
|
178
|
+
[self.retriedServices removeObject:sender.name];
|
|
149
179
|
}
|
|
150
180
|
|
|
151
181
|
// When the service has failed to resolve it's network data (IP addresses, etc)
|
|
152
182
|
- (void) netService:(NSNetService *)sender
|
|
153
183
|
didNotResolve:(NSDictionary *)errorDict
|
|
154
184
|
{
|
|
185
|
+
// Slow devices can time out, retry once before reporting the error (#186)
|
|
186
|
+
NSNumber *code = errorDict[NSNetServicesErrorCode];
|
|
187
|
+
if (code.integerValue == NSNetServicesTimeoutError && ![self.retriedServices containsObject:sender.name]) {
|
|
188
|
+
[self.retriedServices addObject:sender.name];
|
|
189
|
+
[sender resolveWithTimeout:self.resolveTimeoutSeconds];
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
[self.retriedServices removeObject:sender.name];
|
|
193
|
+
|
|
155
194
|
[self reportError:errorDict];
|
|
156
195
|
|
|
157
196
|
sender.delegate = nil;
|
|
@@ -205,8 +244,9 @@ RCT_EXPORT_METHOD(unregisterService:(NSString *) serviceName)
|
|
|
205
244
|
if (self) {
|
|
206
245
|
_resolvingServices = [[NSMutableDictionary alloc] init];
|
|
207
246
|
_publishedServices = [[NSMutableDictionary alloc] init];
|
|
208
|
-
|
|
209
|
-
[
|
|
247
|
+
_retriedServices = [[NSMutableSet alloc] init];
|
|
248
|
+
_stoppingBrowsers = [[NSMutableSet alloc] init];
|
|
249
|
+
_resolveTimeoutSeconds = 5.0;
|
|
210
250
|
}
|
|
211
251
|
|
|
212
252
|
return self;
|
|
@@ -235,12 +275,11 @@ RCT_EXPORT_METHOD(unregisterService:(NSString *) serviceName)
|
|
|
235
275
|
// Called when the bridge is torn down (e.g. reload): stop scanning and unpublish services
|
|
236
276
|
- (void) invalidate
|
|
237
277
|
{
|
|
238
|
-
[self
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
278
|
+
[self stop];
|
|
279
|
+
// Delegates are unretained, detach them so stopping browsers never call a released module
|
|
280
|
+
for (NSNetServiceBrowser *browser in self.stoppingBrowsers) {
|
|
281
|
+
browser.delegate = nil;
|
|
242
282
|
}
|
|
243
|
-
[self.resolvingServices removeAllObjects];
|
|
244
283
|
for (NSNetService *service in self.publishedServices.allValues) {
|
|
245
284
|
service.delegate = nil;
|
|
246
285
|
[service stop];
|