react-native-zeroconf 0.17.2 → 1.0.0-rc.1
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/NOTICE +2 -6
- package/README.md +1 -1
- package/android/CMakeLists.txt +64 -0
- package/android/build.gradle +1 -13
- package/android/generated/java/com/balthazargronon/RCTZeroconf/NativeZeroconfSpec.java +96 -0
- package/android/generated/jni/CMakeLists.txt +28 -0
- package/android/generated/jni/RNZeroconfSpec-generated.cpp +77 -0
- package/android/generated/jni/RNZeroconfSpec.h +31 -0
- package/android/generated/jni/react/renderer/components/RNZeroconfSpec/RNZeroconfSpecJSI.h +798 -0
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/{ZeroconfModule.java → NsdHost.java} +97 -140
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/NsdPayload.java +87 -0
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/NsdPromise.java +40 -0
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/Zeroconf.java +4 -6
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroconfNativeSupport.java +60 -0
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroconfOptions.java +15 -26
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroconfReactPackage.java +5 -15
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/nsd/NsdServiceImpl.java +90 -96
- package/android/src/main/jni/mdnsresponder/mDNSPosix/PosixDaemon.c +19 -1
- package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSPosix.c +104 -1
- package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSPosix.h +7 -0
- package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientshim.c +34 -9
- package/cpp/Backend.cpp +16 -0
- package/cpp/Backend.h +116 -0
- package/cpp/ZeroconfModule.cpp +280 -0
- package/cpp/ZeroconfModule.h +144 -0
- package/cpp/android/NsdBackend.cpp +462 -0
- package/cpp/android/NsdBackend.h +61 -0
- package/cpp/android/ZeroconfAndroidModule.cpp +49 -0
- package/cpp/android/ZeroconfAndroidModule.h +15 -0
- package/cpp/apple/DispatchExecutor.cpp +66 -0
- package/cpp/apple/DispatchExecutor.h +37 -0
- package/cpp/apple/LocalNetworkAccess.h +19 -0
- package/cpp/apple/LocalNetworkAccess.mm +87 -0
- package/cpp/dnssd/DnssdBackend.cpp +976 -0
- package/cpp/dnssd/DnssdBackend.h +114 -0
- package/cpp/dnssd/Executor.h +28 -0
- package/cpp/embedded/EmbeddedExecutor.cpp +124 -0
- package/cpp/embedded/EmbeddedExecutor.h +57 -0
- package/ios/ZeroconfOnLoad.mm +34 -0
- package/ios/generated/ReactCodegen/RNZeroconfSpec/RNZeroconfSpec-generated.mm +140 -0
- package/ios/generated/ReactCodegen/RNZeroconfSpec/RNZeroconfSpec.h +189 -0
- package/ios/generated/ReactCodegen/RNZeroconfSpecJSI.h +798 -0
- package/lib/module/NativeZeroconf.js +15 -0
- package/lib/module/NativeZeroconf.js.map +1 -0
- package/lib/module/bridge.js +124 -0
- package/lib/module/bridge.js.map +1 -0
- package/{dist → lib/module}/index.js +149 -149
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +24 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeZeroconf.d.ts +75 -0
- package/lib/typescript/src/NativeZeroconf.d.ts.map +1 -0
- package/lib/typescript/src/bridge.d.ts +22 -0
- package/lib/typescript/src/bridge.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +111 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +175 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +65 -29
- package/react-native-zeroconf.podspec +2 -1
- package/react-native.config.js +17 -0
- package/src/NativeZeroconf.ts +120 -0
- package/src/bridge.ts +153 -0
- package/src/index.ts +607 -0
- package/{index.d.ts → src/types.ts} +5 -99
- package/windows/RNZeroconf/RNZeroconf.vcxproj +17 -2
- package/windows/RNZeroconf/RNZeroconf.vcxproj.filters +0 -6
- package/windows/RNZeroconf/ReactPackageProvider.cpp +23 -20
- package/windows/RNZeroconf/WindowsBackend.cpp +156 -0
- package/windows/RNZeroconf/WindowsBackend.h +13 -0
- package/windows/RNZeroconf/ZeroconfCore.cpp +2 -2
- package/windows/RNZeroconf/ZeroconfCore.h +2 -2
- package/windows/RNZeroconf/ZeroconfWindowsModule.cpp +22 -0
- package/windows/RNZeroconf/ZeroconfWindowsModule.h +14 -0
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroConfImplFactory.java +0 -56
- package/android/src/main/java/com/balthazargronon/RCTZeroconf/dnssd/DnssdImpl.java +0 -654
- package/android/src/main/java/com/github/druk/dnssd/BaseListener.java +0 -33
- package/android/src/main/java/com/github/druk/dnssd/BrowseListener.java +0 -67
- package/android/src/main/java/com/github/druk/dnssd/DNSRecord.java +0 -47
- package/android/src/main/java/com/github/druk/dnssd/DNSSD.java +0 -650
- package/android/src/main/java/com/github/druk/dnssd/DNSSDEmbedded.java +0 -135
- package/android/src/main/java/com/github/druk/dnssd/DNSSDException.java +0 -66
- package/android/src/main/java/com/github/druk/dnssd/DNSSDRecordRegistrar.java +0 -55
- package/android/src/main/java/com/github/druk/dnssd/DNSSDRegistration.java +0 -54
- package/android/src/main/java/com/github/druk/dnssd/DNSSDService.java +0 -35
- package/android/src/main/java/com/github/druk/dnssd/DomainListener.java +0 -57
- package/android/src/main/java/com/github/druk/dnssd/InternalBrowseListener.java +0 -76
- package/android/src/main/java/com/github/druk/dnssd/InternalDNSSD.java +0 -870
- package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDRecordRegistrar.java +0 -30
- package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDRegistration.java +0 -34
- package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDService.java +0 -29
- package/android/src/main/java/com/github/druk/dnssd/InternalDomainListener.java +0 -62
- package/android/src/main/java/com/github/druk/dnssd/InternalQueryListener.java +0 -61
- package/android/src/main/java/com/github/druk/dnssd/InternalRegisterListener.java +0 -51
- package/android/src/main/java/com/github/druk/dnssd/InternalResolveListener.java +0 -58
- package/android/src/main/java/com/github/druk/dnssd/NSClass.java +0 -16
- package/android/src/main/java/com/github/druk/dnssd/NSType.java +0 -58
- package/android/src/main/java/com/github/druk/dnssd/QueryListener.java +0 -54
- package/android/src/main/java/com/github/druk/dnssd/RegisterListener.java +0 -46
- package/android/src/main/java/com/github/druk/dnssd/RegisterRecordListener.java +0 -35
- package/android/src/main/java/com/github/druk/dnssd/ResolveListener.java +0 -55
- package/android/src/main/java/com/github/druk/dnssd/TXTRecord.java +0 -293
- package/android/src/main/jni/Android.mk +0 -73
- package/android/src/main/jni/Application.mk +0 -3
- package/android/src/main/jni/DNSSD.java.h +0 -290
- package/android/src/main/jni/JNISupport.c +0 -1140
- package/ios/RNZeroconf/RNNetServiceSerializer.h +0 -31
- package/ios/RNZeroconf/RNNetServiceSerializer.m +0 -84
- package/ios/RNZeroconf/RNZeroconf.h +0 -17
- package/ios/RNZeroconf/RNZeroconf.m +0 -1025
- package/ios/RNZeroconf.xcodeproj/project.pbxproj +0 -261
- package/ios/RNZeroconf.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/src/index.js +0 -563
- package/windows/RNZeroconf/RNZeroconf.cpp +0 -228
- package/windows/RNZeroconf/RNZeroconf.h +0 -70
|
@@ -505,7 +505,7 @@ mDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
|
|
|
505
505
|
{
|
|
506
506
|
char line[256];
|
|
507
507
|
char nameserver[16];
|
|
508
|
-
char keyword[
|
|
508
|
+
char keyword[11]; // "%10s" writes up to 10 characters and the terminator
|
|
509
509
|
int numOfServers = 0;
|
|
510
510
|
FILE *fp = fopen(filePath, "r");
|
|
511
511
|
if (fp == NULL) return -1;
|
|
@@ -1333,6 +1333,107 @@ mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
|
|
|
1333
1333
|
#pragma mark ***** Locking
|
|
1334
1334
|
#endif
|
|
1335
1335
|
|
|
1336
|
+
#ifdef EMBEDDED
|
|
1337
|
+
|
|
1338
|
+
// The embedded build enters mDNS core from several threads: the DNS-SDEmbedded thread
|
|
1339
|
+
// runs mDNS_Execute() and delivers the callbacks, while the DNSService* calls, and in
|
|
1340
|
+
// particular DNSServiceRefDeallocate(), arrive on whatever thread the client uses.
|
|
1341
|
+
// mDNS core relies on mDNSPlatformLock() for mutual exclusion between those, so here it
|
|
1342
|
+
// is a real lock. It is recursive because the core holds it while it calls back into the
|
|
1343
|
+
// client, and the client may call back into the core from there (see mDNS_DropLockBeforeCallback).
|
|
1344
|
+
|
|
1345
|
+
#include <pthread.h>
|
|
1346
|
+
|
|
1347
|
+
static pthread_mutex_t gCoreLock;
|
|
1348
|
+
static pthread_once_t gCoreLockOnce = PTHREAD_ONCE_INIT;
|
|
1349
|
+
|
|
1350
|
+
// The event loop sleeps in select() until the core's next scheduled event. A DNSService* call
|
|
1351
|
+
// from another thread changes that schedule (a new question has to be answered now), so when
|
|
1352
|
+
// such a call releases the lock, the loop is woken through a pipe it listens to. Otherwise the
|
|
1353
|
+
// call would wait for the next timer or the next packet from the network.
|
|
1354
|
+
// The pipe is created together with the lock and lives as long as the process, so that the
|
|
1355
|
+
// write in mDNSPlatformUnlock() can never hit a descriptor another thread has closed and reused.
|
|
1356
|
+
static pthread_t gLoopThread;
|
|
1357
|
+
static int gLoopThreadSet = 0;
|
|
1358
|
+
static int gWakePipe[2] = { -1, -1 };
|
|
1359
|
+
|
|
1360
|
+
static void WakeCallback(int fd, short filter, void *context)
|
|
1361
|
+
{
|
|
1362
|
+
char buffer[64];
|
|
1363
|
+
(void) filter; // Unused
|
|
1364
|
+
(void) context; // Unused
|
|
1365
|
+
while (read(fd, buffer, sizeof(buffer)) > 0) { }
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
static void InitCoreLockAndWakePipe(void)
|
|
1369
|
+
{
|
|
1370
|
+
pthread_mutexattr_t attr;
|
|
1371
|
+
pthread_mutexattr_init(&attr);
|
|
1372
|
+
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
|
1373
|
+
pthread_mutex_init(&gCoreLock, &attr);
|
|
1374
|
+
pthread_mutexattr_destroy(&attr);
|
|
1375
|
+
if (pipe(gWakePipe) == 0)
|
|
1376
|
+
{
|
|
1377
|
+
fcntl(gWakePipe[0], F_SETFL, fcntl(gWakePipe[0], F_GETFL, 0) | O_NONBLOCK);
|
|
1378
|
+
fcntl(gWakePipe[1], F_SETFL, fcntl(gWakePipe[1], F_GETFL, 0) | O_NONBLOCK);
|
|
1379
|
+
}
|
|
1380
|
+
else
|
|
1381
|
+
{
|
|
1382
|
+
gWakePipe[0] = gWakePipe[1] = -1;
|
|
1383
|
+
LogMsg("mDNSPosix: pipe() failed (%d), other threads will not wake the event loop", errno);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
mDNSexport void mDNSPosixEmbeddedLoopStarting(void)
|
|
1388
|
+
{
|
|
1389
|
+
mDNSPlatformLock(mDNSNULL);
|
|
1390
|
+
gLoopThread = pthread_self();
|
|
1391
|
+
gLoopThreadSet = 1;
|
|
1392
|
+
if (gWakePipe[0] >= 0)
|
|
1393
|
+
{
|
|
1394
|
+
mStatus err = mDNSPosixAddFDToEventLoop(gWakePipe[0], WakeCallback, mDNSNULL);
|
|
1395
|
+
if (err) LogMsg("mDNSPosix: cannot listen to the wake-up pipe (%d), other threads will not wake the event loop", err);
|
|
1396
|
+
}
|
|
1397
|
+
mDNSPlatformUnlock(mDNSNULL);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
mDNSexport void mDNSPosixEmbeddedLoopStopping(void)
|
|
1401
|
+
{
|
|
1402
|
+
mDNSPlatformLock(mDNSNULL);
|
|
1403
|
+
if (gWakePipe[0] >= 0)
|
|
1404
|
+
{
|
|
1405
|
+
mDNSPosixRemoveFDFromEventLoop(gWakePipe[0]);
|
|
1406
|
+
WakeCallback(gWakePipe[0], 0, mDNSNULL); // Drain, for the next loop
|
|
1407
|
+
}
|
|
1408
|
+
gLoopThreadSet = 0;
|
|
1409
|
+
mDNSPlatformUnlock(mDNSNULL);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
mDNSexport void mDNSPosixEmbeddedWakeLoop(void)
|
|
1413
|
+
{
|
|
1414
|
+
if (gWakePipe[1] >= 0)
|
|
1415
|
+
{
|
|
1416
|
+
if (write(gWakePipe[1], "", 1) < 0) { } // A full pipe means the loop is about to wake anyway
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
mDNSexport void mDNSPlatformLock (const mDNS *const m)
|
|
1421
|
+
{
|
|
1422
|
+
(void) m; // Unused
|
|
1423
|
+
pthread_once(&gCoreLockOnce, InitCoreLockAndWakePipe);
|
|
1424
|
+
pthread_mutex_lock(&gCoreLock);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
mDNSexport void mDNSPlatformUnlock (const mDNS *const m)
|
|
1428
|
+
{
|
|
1429
|
+
(void) m; // Unused
|
|
1430
|
+
int fromLoopThread = gLoopThreadSet && pthread_equal(pthread_self(), gLoopThread);
|
|
1431
|
+
pthread_mutex_unlock(&gCoreLock);
|
|
1432
|
+
if (!fromLoopThread) mDNSPosixEmbeddedWakeLoop();
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
#else
|
|
1436
|
+
|
|
1336
1437
|
// On the Posix platform, locking is a no-op because we only ever enter
|
|
1337
1438
|
// mDNS core on the main thread.
|
|
1338
1439
|
|
|
@@ -1350,6 +1451,8 @@ mDNSexport void mDNSPlatformUnlock (const mDNS *const m)
|
|
|
1350
1451
|
(void) m; // Unused
|
|
1351
1452
|
}
|
|
1352
1453
|
|
|
1454
|
+
#endif // EMBEDDED
|
|
1455
|
+
|
|
1353
1456
|
#if COMPILER_LIKES_PRAGMA_MARK
|
|
1354
1457
|
#pragma mark ***** Strings
|
|
1355
1458
|
#endif
|
|
@@ -81,6 +81,13 @@ extern mStatus mDNSPosixListenForSignalInEventLoop( int signum);
|
|
|
81
81
|
extern mStatus mDNSPosixIgnoreSignalInEventLoop( int signum);
|
|
82
82
|
extern mStatus mDNSPosixRunEventLoopOnce( mDNS *m, const struct timeval *pTimeout, sigset_t *pSignalsReceived, mDNSBool *pDataDispatched);
|
|
83
83
|
|
|
84
|
+
#ifdef EMBEDDED
|
|
85
|
+
// The embedded build is driven from several threads, see the locking section of mDNSPosix.c.
|
|
86
|
+
extern void mDNSPosixEmbeddedLoopStarting(void); // Call on the event loop thread, before running the loop
|
|
87
|
+
extern void mDNSPosixEmbeddedLoopStopping(void); // Call on the event loop thread, after the loop returned
|
|
88
|
+
extern void mDNSPosixEmbeddedWakeLoop(void); // Make the loop re-read the schedule and stop flags
|
|
89
|
+
#endif
|
|
90
|
+
|
|
84
91
|
#ifdef __cplusplus
|
|
85
92
|
}
|
|
86
93
|
#endif
|
|
@@ -80,6 +80,7 @@ typedef struct
|
|
|
80
80
|
{
|
|
81
81
|
mDNS_DirectOP_Dispose *disposefn;
|
|
82
82
|
DNSServiceRef aQuery;
|
|
83
|
+
DNSServiceRef aaaaQuery; // react-native-zeroconf: IPv6 addresses too
|
|
83
84
|
DNSServiceGetAddrInfoReply callback;
|
|
84
85
|
void *context;
|
|
85
86
|
} mDNS_DirectOP_GetAddrInfo;
|
|
@@ -198,8 +199,9 @@ mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus re
|
|
|
198
199
|
|
|
199
200
|
if (result == mStatus_NoError)
|
|
200
201
|
{
|
|
202
|
+
// react-native-zeroconf: kDNSServiceFlagsAdd marks a registration, as with Apple's implementation
|
|
201
203
|
if (x->callback)
|
|
202
|
-
x->callback((DNSServiceRef)x,
|
|
204
|
+
x->callback((DNSServiceRef)x, kDNSServiceFlagsAdd, result, namestr, typestr, domstr, x->context);
|
|
203
205
|
}
|
|
204
206
|
else if (result == mStatus_NameConflict)
|
|
205
207
|
{
|
|
@@ -701,10 +703,10 @@ DNSServiceErrorType DNSServiceQueryRecord
|
|
|
701
703
|
x->callback = callback;
|
|
702
704
|
x->context = context;
|
|
703
705
|
|
|
704
|
-
x->q.ThisQInterval = -1; // So that
|
|
706
|
+
x->q.ThisQInterval = -1; // So that DNSServiceQueryRecordDispose() knows whether to cancel this question
|
|
705
707
|
x->q.InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
|
|
706
708
|
x->q.Target = zeroAddr;
|
|
707
|
-
MakeDomainNameFromDNSNameString(&x->q.qname, fullname);
|
|
709
|
+
if (!MakeDomainNameFromDNSNameString(&x->q.qname, fullname)) { mDNSPlatformMemFree(x); err = mStatus_BadParamErr; errormsg = "MakeDomainNameFromDNSNameString"; goto fail; }
|
|
708
710
|
x->q.qtype = rrtype;
|
|
709
711
|
x->q.qclass = rrclass;
|
|
710
712
|
x->q.LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
|
|
@@ -721,7 +723,7 @@ DNSServiceErrorType DNSServiceQueryRecord
|
|
|
721
723
|
x->q.QuestionContext = x;
|
|
722
724
|
|
|
723
725
|
err = mDNS_StartQuery(&mDNSStorage, &x->q);
|
|
724
|
-
if (err) {
|
|
726
|
+
if (err) { DNSServiceQueryRecordDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
|
|
725
727
|
|
|
726
728
|
// Succeeded: Wrap up and return
|
|
727
729
|
*sdRef = (DNSServiceRef)x;
|
|
@@ -739,6 +741,7 @@ static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op)
|
|
|
739
741
|
{
|
|
740
742
|
mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op;
|
|
741
743
|
if (x->aQuery) DNSServiceRefDeallocate(x->aQuery);
|
|
744
|
+
if (x->aaaaQuery) DNSServiceRefDeallocate(x->aaaaQuery);
|
|
742
745
|
mDNSPlatformMemFree(x);
|
|
743
746
|
}
|
|
744
747
|
|
|
@@ -757,16 +760,27 @@ static void DNSSD_API DNSServiceGetAddrInfoResponse(
|
|
|
757
760
|
{
|
|
758
761
|
mDNS_DirectOP_GetAddrInfo * x = (mDNS_DirectOP_GetAddrInfo*)inContext;
|
|
759
762
|
struct sockaddr_in sa4;
|
|
763
|
+
struct sockaddr_in6 sa6;
|
|
764
|
+
const struct sockaddr * sa = (const struct sockaddr *) &sa4;
|
|
760
765
|
|
|
761
766
|
mDNSPlatformMemZero(&sa4, sizeof(sa4));
|
|
762
|
-
|
|
767
|
+
mDNSPlatformMemZero(&sa6, sizeof(sa6));
|
|
768
|
+
if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_A && inRDLen == 4)
|
|
763
769
|
{
|
|
764
770
|
sa4.sin_family = AF_INET;
|
|
765
771
|
mDNSPlatformMemCopy(&sa4.sin_addr.s_addr, inRData, 4);
|
|
766
772
|
}
|
|
773
|
+
else if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_AAAA && inRDLen == 16)
|
|
774
|
+
{
|
|
775
|
+
// react-native-zeroconf: AAAA answers become IPv6 addresses, as with Apple's implementation
|
|
776
|
+
sa6.sin6_family = AF_INET6;
|
|
777
|
+
mDNSPlatformMemCopy(&sa6.sin6_addr, inRData, 16);
|
|
778
|
+
sa6.sin6_scope_id = inInterfaceIndex;
|
|
779
|
+
sa = (const struct sockaddr *) &sa6;
|
|
780
|
+
}
|
|
767
781
|
|
|
768
782
|
x->callback((DNSServiceRef)x, inFlags, inInterfaceIndex, inErrorCode, inFullName,
|
|
769
|
-
|
|
783
|
+
sa, inTTL, x->context);
|
|
770
784
|
}
|
|
771
785
|
|
|
772
786
|
DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
|
|
@@ -791,14 +805,25 @@ DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
|
|
|
791
805
|
x->callback = inCallback;
|
|
792
806
|
x->context = inContext;
|
|
793
807
|
x->aQuery = mDNSNULL;
|
|
808
|
+
x->aaaaQuery = mDNSNULL;
|
|
794
809
|
|
|
795
810
|
// Start the query.
|
|
796
811
|
// (It would probably be more efficient to code this using mDNS_StartQuery directly,
|
|
797
812
|
// instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
|
|
798
813
|
// more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
814
|
+
// react-native-zeroconf: an A query for IPv4 and an AAAA query for IPv6, both without a protocol
|
|
815
|
+
if (!inProtocol || (inProtocol & kDNSServiceProtocol_IPv4))
|
|
816
|
+
{
|
|
817
|
+
err = DNSServiceQueryRecord(&x->aQuery, inFlags, inInterfaceIndex, inHostName, kDNSServiceType_A,
|
|
818
|
+
kDNSServiceClass_IN, DNSServiceGetAddrInfoResponse, x);
|
|
819
|
+
if (err) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP*)x); errormsg = "DNSServiceQueryRecord"; goto fail; }
|
|
820
|
+
}
|
|
821
|
+
if (!inProtocol || (inProtocol & kDNSServiceProtocol_IPv6))
|
|
822
|
+
{
|
|
823
|
+
err = DNSServiceQueryRecord(&x->aaaaQuery, inFlags, inInterfaceIndex, inHostName, kDNSServiceType_AAAA,
|
|
824
|
+
kDNSServiceClass_IN, DNSServiceGetAddrInfoResponse, x);
|
|
825
|
+
if (err) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP*)x); errormsg = "DNSServiceQueryRecord"; goto fail; }
|
|
826
|
+
}
|
|
802
827
|
|
|
803
828
|
*outRef = (DNSServiceRef)x;
|
|
804
829
|
return(mStatus_NoError);
|
package/cpp/Backend.cpp
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#include "Backend.h"
|
|
2
|
+
|
|
3
|
+
namespace rnzeroconf {
|
|
4
|
+
|
|
5
|
+
Error LibraryError(const std::string &code, const std::string &message, const std::string &serviceName) {
|
|
6
|
+
return Error{"RNZeroconf", code, message, serviceName};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
std::string SubtypeLabel(const std::string &subtype) {
|
|
10
|
+
if (subtype.empty() || subtype[0] == '_') {
|
|
11
|
+
return subtype;
|
|
12
|
+
}
|
|
13
|
+
return "_" + subtype;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
} // namespace rnzeroconf
|
package/cpp/Backend.h
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// What a platform implements: scanning, resolving and publishing on one mDNS stack.
|
|
2
|
+
// No React Native dependency: ZeroconfModule bridges a backend to JavaScript, the native harnesses test it directly.
|
|
3
|
+
// Strings are UTF-8. Callbacks run on the backend's own thread.
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
#include <functional>
|
|
8
|
+
#include <optional>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <utility>
|
|
11
|
+
#include <vector>
|
|
12
|
+
|
|
13
|
+
namespace rnzeroconf {
|
|
14
|
+
|
|
15
|
+
// TXT records as ordered [key, value] pairs
|
|
16
|
+
using TxtPairs = std::vector<std::pair<std::string, std::string>>;
|
|
17
|
+
|
|
18
|
+
struct Service {
|
|
19
|
+
std::string name;
|
|
20
|
+
std::string fullName;
|
|
21
|
+
std::string host;
|
|
22
|
+
uint16_t port = 0;
|
|
23
|
+
std::vector<std::string> addresses;
|
|
24
|
+
TxtPairs txt;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// { message, code, domain, serviceName } as JavaScript sees it.
|
|
28
|
+
// The code is a string for domain "RNZeroconf" ('TIMEOUT'), the platform's number otherwise (-65555)
|
|
29
|
+
struct Error {
|
|
30
|
+
std::string domain;
|
|
31
|
+
std::string code;
|
|
32
|
+
std::string message;
|
|
33
|
+
std::string serviceName;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
Error LibraryError(const std::string &code, const std::string &message, const std::string &serviceName = "");
|
|
37
|
+
|
|
38
|
+
using ServiceCallback = std::function<void(const Service &)>;
|
|
39
|
+
using ErrorCallback = std::function<void(const Error &)>;
|
|
40
|
+
|
|
41
|
+
// Scan events carry the id of the scan they belong to. An error with an empty scanId is not about a scan
|
|
42
|
+
struct Events {
|
|
43
|
+
std::function<void(const std::string &scanId)> start;
|
|
44
|
+
std::function<void(const std::string &scanId)> stop;
|
|
45
|
+
std::function<void(const std::string &scanId, const std::string &name)> found;
|
|
46
|
+
std::function<void(const std::string &scanId, const std::string &name)> remove;
|
|
47
|
+
std::function<void(const std::string &scanId, const Service &)> resolved;
|
|
48
|
+
std::function<void(const Service &)> published;
|
|
49
|
+
std::function<void(const Service &)> unpublished;
|
|
50
|
+
std::function<void(const std::string &scanId, const Error &)> error;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
struct ScanOptions {
|
|
54
|
+
// "printer" or "_printer", empty for none
|
|
55
|
+
std::string subtype;
|
|
56
|
+
// "en0", empty for every interface
|
|
57
|
+
std::string networkInterface;
|
|
58
|
+
// Each found service is resolved for this long, retried once, then reported with a TIMEOUT error
|
|
59
|
+
double resolveTimeoutSeconds = 5;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
struct PublishOptions {
|
|
63
|
+
std::vector<std::string> subtypes;
|
|
64
|
+
std::string networkInterface;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
struct ResolveOptions {
|
|
68
|
+
std::string networkInterface;
|
|
69
|
+
double timeoutSeconds = 5;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
class Backend {
|
|
73
|
+
public:
|
|
74
|
+
virtual ~Backend() = default;
|
|
75
|
+
|
|
76
|
+
// type and protocol without underscore ("http", "tcp"); "services._dns-sd" / "udp" lists the service types.
|
|
77
|
+
// Starting a scan with the id of a running one replaces it
|
|
78
|
+
virtual void Scan(
|
|
79
|
+
const std::string &scanId,
|
|
80
|
+
const std::string &type,
|
|
81
|
+
const std::string &protocol,
|
|
82
|
+
const std::string &domain,
|
|
83
|
+
const ScanOptions &options) = 0;
|
|
84
|
+
// Stops the scan with this id, or every scan with an empty one
|
|
85
|
+
virtual void Stop(const std::string &scanId) = 0;
|
|
86
|
+
|
|
87
|
+
virtual void Publish(
|
|
88
|
+
const std::string &type,
|
|
89
|
+
const std::string &protocol,
|
|
90
|
+
const std::string &domain,
|
|
91
|
+
const std::string &name,
|
|
92
|
+
uint16_t port,
|
|
93
|
+
const TxtPairs &txt,
|
|
94
|
+
const PublishOptions &options,
|
|
95
|
+
ServiceCallback resolve,
|
|
96
|
+
ErrorCallback reject) = 0;
|
|
97
|
+
virtual void Unpublish(const std::string &name, ServiceCallback resolve, ErrorCallback reject) = 0;
|
|
98
|
+
virtual void Update(const std::string &name, const TxtPairs &txt, ServiceCallback resolve, ErrorCallback reject) = 0;
|
|
99
|
+
|
|
100
|
+
virtual void ResolveService(
|
|
101
|
+
const std::string &name,
|
|
102
|
+
const std::string &type,
|
|
103
|
+
const std::string &protocol,
|
|
104
|
+
const std::string &domain,
|
|
105
|
+
const ResolveOptions &options,
|
|
106
|
+
ServiceCallback resolve,
|
|
107
|
+
ErrorCallback reject) = 0;
|
|
108
|
+
|
|
109
|
+
// Stops the scans and unpublishes the services, when the module goes away
|
|
110
|
+
virtual void Shutdown() = 0;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// "printer" or "_printer" -> "_printer", empty stays empty
|
|
114
|
+
std::string SubtypeLabel(const std::string &subtype);
|
|
115
|
+
|
|
116
|
+
} // namespace rnzeroconf
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#include "ZeroconfModule.h"
|
|
2
|
+
|
|
3
|
+
#include <utility>
|
|
4
|
+
|
|
5
|
+
namespace facebook::react {
|
|
6
|
+
|
|
7
|
+
namespace {
|
|
8
|
+
|
|
9
|
+
rnzeroconf::TxtPairs ToTxt(const std::vector<ZeroconfTxtEntry> &entries) {
|
|
10
|
+
rnzeroconf::TxtPairs txt;
|
|
11
|
+
for (const auto &entry : entries) {
|
|
12
|
+
txt.emplace_back(entry.key, entry.value);
|
|
13
|
+
}
|
|
14
|
+
return txt;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
ZeroconfService ToJs(const rnzeroconf::Service &service) {
|
|
18
|
+
std::vector<ZeroconfTxtEntry> txt;
|
|
19
|
+
for (const auto &[key, value] : service.txt) {
|
|
20
|
+
txt.push_back(ZeroconfTxtEntry{key, value});
|
|
21
|
+
}
|
|
22
|
+
return ZeroconfService{service.name, service.fullName, service.host, static_cast<double>(service.port), service.addresses, txt};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ZeroconfError ToJs(const rnzeroconf::Error &error) {
|
|
26
|
+
return ZeroconfError{error.message, error.code, error.domain, error.serviceName};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
} // namespace
|
|
30
|
+
|
|
31
|
+
ZeroconfModule::ZeroconfModule(std::shared_ptr<CallInvoker> jsInvoker, ZeroconfPlatform platform)
|
|
32
|
+
: NativeZeroconfCxxSpec(std::move(jsInvoker)), platform_(std::move(platform)), emitter_(std::make_shared<Emitter>()) {
|
|
33
|
+
emitter_->module = this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ZeroconfModule::~ZeroconfModule() {
|
|
37
|
+
{
|
|
38
|
+
std::lock_guard<std::mutex> lock(emitter_->mutex);
|
|
39
|
+
emitter_->module = nullptr;
|
|
40
|
+
}
|
|
41
|
+
{
|
|
42
|
+
std::lock_guard<std::mutex> lock(activityMutex_);
|
|
43
|
+
if (active_ && platform_.setActive) {
|
|
44
|
+
platform_.setActive(false);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Stops the scans and unpublishes the services, on reload for example
|
|
48
|
+
std::lock_guard<std::mutex> lock(backendsMutex_);
|
|
49
|
+
for (auto &entry : backends_) {
|
|
50
|
+
entry.second->Shutdown();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
std::shared_ptr<rnzeroconf::Backend> ZeroconfModule::Backend(const std::string &implType) {
|
|
55
|
+
std::string key = platform_.backendKey ? platform_.backendKey(implType) : implType;
|
|
56
|
+
std::lock_guard<std::mutex> lock(backendsMutex_);
|
|
57
|
+
auto found = backends_.find(key);
|
|
58
|
+
if (found != backends_.end()) {
|
|
59
|
+
return found->second;
|
|
60
|
+
}
|
|
61
|
+
auto backend = platform_.createBackend(key, MakeEvents());
|
|
62
|
+
backends_[key] = backend;
|
|
63
|
+
return backend;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
rnzeroconf::Events ZeroconfModule::MakeEvents() {
|
|
67
|
+
std::weak_ptr<Emitter> weak = emitter_;
|
|
68
|
+
// Runs an emit while the module exists
|
|
69
|
+
auto with = [weak](const std::function<void(ZeroconfModule &)> &emit) {
|
|
70
|
+
auto emitter = weak.lock();
|
|
71
|
+
if (!emitter) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
std::lock_guard<std::mutex> lock(emitter->mutex);
|
|
75
|
+
if (emitter->module) {
|
|
76
|
+
emit(*emitter->module);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
rnzeroconf::Events events;
|
|
81
|
+
events.start = [with](const std::string &scanId) {
|
|
82
|
+
with([&](ZeroconfModule &module) { module.emitOnStart(ZeroconfScanEvent{scanId}); });
|
|
83
|
+
};
|
|
84
|
+
events.stop = [with](const std::string &scanId) {
|
|
85
|
+
with([&](ZeroconfModule &module) {
|
|
86
|
+
// Also when the scan ended by itself, after an error
|
|
87
|
+
module.Track(Activity::ScanStopped, scanId);
|
|
88
|
+
module.emitOnStop(ZeroconfScanEvent{scanId});
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
events.found = [with](const std::string &scanId, const std::string &name) {
|
|
92
|
+
with([&](ZeroconfModule &module) { module.emitOnFound(ZeroconfNameEvent{scanId, name}); });
|
|
93
|
+
};
|
|
94
|
+
events.remove = [with](const std::string &scanId, const std::string &name) {
|
|
95
|
+
with([&](ZeroconfModule &module) { module.emitOnRemove(ZeroconfNameEvent{scanId, name}); });
|
|
96
|
+
};
|
|
97
|
+
events.resolved = [with](const std::string &scanId, const rnzeroconf::Service &service) {
|
|
98
|
+
with([&](ZeroconfModule &module) { module.emitOnResolved(ZeroconfResolvedEvent{scanId, ToJs(service)}); });
|
|
99
|
+
};
|
|
100
|
+
events.published = [with](const rnzeroconf::Service &service) {
|
|
101
|
+
with([&](ZeroconfModule &module) {
|
|
102
|
+
module.Track(Activity::Published, service.name);
|
|
103
|
+
module.emitOnPublished(ToJs(service));
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
events.unpublished = [with](const rnzeroconf::Service &service) {
|
|
107
|
+
with([&](ZeroconfModule &module) {
|
|
108
|
+
module.Track(Activity::Unpublished, service.name);
|
|
109
|
+
module.emitOnUnpublished(ToJs(service));
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
events.error = [with](const std::string &scanId, const rnzeroconf::Error &error) {
|
|
113
|
+
with([&](ZeroconfModule &module) { module.emitOnError(ZeroconfErrorEvent{scanId, ToJs(error)}); });
|
|
114
|
+
};
|
|
115
|
+
return events;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
AsyncPromise<ZeroconfResult> ZeroconfModule::Settle(
|
|
119
|
+
jsi::Runtime &rt,
|
|
120
|
+
const std::function<void(rnzeroconf::ServiceCallback, rnzeroconf::ErrorCallback)> &call,
|
|
121
|
+
bool active) {
|
|
122
|
+
AsyncPromise<ZeroconfResult> promise(rt, jsInvoker_);
|
|
123
|
+
// Publishes and resolves need the network until they settle
|
|
124
|
+
std::shared_ptr<bool> settled;
|
|
125
|
+
if (active) {
|
|
126
|
+
Track(Activity::CallStarted);
|
|
127
|
+
settled = std::make_shared<bool>(false);
|
|
128
|
+
}
|
|
129
|
+
std::weak_ptr<Emitter> weak = emitter_;
|
|
130
|
+
auto done = [weak, settled] {
|
|
131
|
+
if (!settled || *settled) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
*settled = true;
|
|
135
|
+
if (auto emitter = weak.lock()) {
|
|
136
|
+
std::lock_guard<std::mutex> lock(emitter->mutex);
|
|
137
|
+
if (emitter->module) {
|
|
138
|
+
emitter->module->Track(Activity::CallSettled);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
call(
|
|
143
|
+
[promise, done](const rnzeroconf::Service &service) mutable {
|
|
144
|
+
done();
|
|
145
|
+
promise.resolve(ZeroconfResult{ToJs(service), std::nullopt});
|
|
146
|
+
},
|
|
147
|
+
[promise, done](const rnzeroconf::Error &error) mutable {
|
|
148
|
+
done();
|
|
149
|
+
promise.resolve(ZeroconfResult{std::nullopt, ToJs(error)});
|
|
150
|
+
});
|
|
151
|
+
return promise;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
void ZeroconfModule::Track(Activity activity, const std::string &key) {
|
|
155
|
+
std::lock_guard<std::mutex> lock(activityMutex_);
|
|
156
|
+
switch (activity) {
|
|
157
|
+
case Activity::ScanStarted:
|
|
158
|
+
runningScans_.insert(key);
|
|
159
|
+
break;
|
|
160
|
+
case Activity::ScanStopped:
|
|
161
|
+
runningScans_.erase(key);
|
|
162
|
+
break;
|
|
163
|
+
case Activity::AllScansStopped:
|
|
164
|
+
runningScans_.clear();
|
|
165
|
+
break;
|
|
166
|
+
case Activity::Published:
|
|
167
|
+
publishedServices_.insert(key);
|
|
168
|
+
break;
|
|
169
|
+
case Activity::Unpublished:
|
|
170
|
+
publishedServices_.erase(key);
|
|
171
|
+
break;
|
|
172
|
+
case Activity::CallStarted:
|
|
173
|
+
callsInFlight_++;
|
|
174
|
+
break;
|
|
175
|
+
case Activity::CallSettled:
|
|
176
|
+
callsInFlight_--;
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
bool active = !runningScans_.empty() || !publishedServices_.empty() || callsInFlight_ > 0;
|
|
180
|
+
if (active != active_) {
|
|
181
|
+
active_ = active;
|
|
182
|
+
if (platform_.setActive) {
|
|
183
|
+
platform_.setActive(active);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void ZeroconfModule::scan(
|
|
189
|
+
jsi::Runtime &,
|
|
190
|
+
std::string scanId,
|
|
191
|
+
std::string type,
|
|
192
|
+
std::string protocol,
|
|
193
|
+
std::string domain,
|
|
194
|
+
std::string implType,
|
|
195
|
+
ZeroconfScanOptions options) {
|
|
196
|
+
rnzeroconf::ScanOptions scanOptions;
|
|
197
|
+
scanOptions.resolveTimeoutSeconds = options.resolveTimeout.value_or(5);
|
|
198
|
+
scanOptions.subtype = options.subtype.value_or("");
|
|
199
|
+
scanOptions.networkInterface = options.networkInterface.value_or("");
|
|
200
|
+
Track(Activity::ScanStarted, scanId);
|
|
201
|
+
Backend(implType)->Scan(scanId, type, protocol, domain, scanOptions);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
void ZeroconfModule::stop(jsi::Runtime &, std::string scanId, std::string implType) {
|
|
205
|
+
Track(scanId.empty() ? Activity::AllScansStopped : Activity::ScanStopped, scanId);
|
|
206
|
+
Backend(implType)->Stop(scanId);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
AsyncPromise<ZeroconfResult> ZeroconfModule::registerService(
|
|
210
|
+
jsi::Runtime &rt,
|
|
211
|
+
std::string type,
|
|
212
|
+
std::string protocol,
|
|
213
|
+
std::string domain,
|
|
214
|
+
std::string name,
|
|
215
|
+
double port,
|
|
216
|
+
std::vector<ZeroconfTxtEntry> txt,
|
|
217
|
+
std::string implType,
|
|
218
|
+
ZeroconfPublishOptions options) {
|
|
219
|
+
rnzeroconf::PublishOptions publishOptions;
|
|
220
|
+
publishOptions.subtypes = options.subtypes.value_or(std::vector<std::string>{});
|
|
221
|
+
publishOptions.networkInterface = options.networkInterface.value_or("");
|
|
222
|
+
auto backend = Backend(implType);
|
|
223
|
+
return Settle(
|
|
224
|
+
rt,
|
|
225
|
+
[&](rnzeroconf::ServiceCallback resolve, rnzeroconf::ErrorCallback reject) {
|
|
226
|
+
backend->Publish(type, protocol, domain, name, static_cast<uint16_t>(port), ToTxt(txt), publishOptions, std::move(resolve), std::move(reject));
|
|
227
|
+
},
|
|
228
|
+
true);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
AsyncPromise<ZeroconfResult> ZeroconfModule::updateService(jsi::Runtime &rt, std::string name, std::vector<ZeroconfTxtEntry> txt, std::string implType) {
|
|
232
|
+
auto backend = Backend(implType);
|
|
233
|
+
return Settle(rt, [&](rnzeroconf::ServiceCallback resolve, rnzeroconf::ErrorCallback reject) {
|
|
234
|
+
backend->Update(name, ToTxt(txt), std::move(resolve), std::move(reject));
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
AsyncPromise<ZeroconfResult> ZeroconfModule::unregisterService(jsi::Runtime &rt, std::string name, std::string implType) {
|
|
239
|
+
auto backend = Backend(implType);
|
|
240
|
+
return Settle(rt, [&](rnzeroconf::ServiceCallback resolve, rnzeroconf::ErrorCallback reject) {
|
|
241
|
+
backend->Unpublish(name, std::move(resolve), std::move(reject));
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
AsyncPromise<ZeroconfResult> ZeroconfModule::resolveService(
|
|
246
|
+
jsi::Runtime &rt,
|
|
247
|
+
std::string name,
|
|
248
|
+
std::string type,
|
|
249
|
+
std::string protocol,
|
|
250
|
+
std::string domain,
|
|
251
|
+
std::string implType,
|
|
252
|
+
ZeroconfResolveOptions options) {
|
|
253
|
+
rnzeroconf::ResolveOptions resolveOptions;
|
|
254
|
+
resolveOptions.timeoutSeconds = options.timeout.value_or(5);
|
|
255
|
+
resolveOptions.networkInterface = options.networkInterface.value_or("");
|
|
256
|
+
auto backend = Backend(implType);
|
|
257
|
+
return Settle(
|
|
258
|
+
rt,
|
|
259
|
+
[&](rnzeroconf::ServiceCallback resolve, rnzeroconf::ErrorCallback reject) {
|
|
260
|
+
backend->ResolveService(name, type, protocol, domain, resolveOptions, std::move(resolve), std::move(reject));
|
|
261
|
+
},
|
|
262
|
+
true);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
AsyncPromise<ZeroconfAccessResult> ZeroconfModule::checkLocalNetworkAccess(jsi::Runtime &rt, std::string type, double timeout) {
|
|
266
|
+
AsyncPromise<ZeroconfAccessResult> promise(rt, jsInvoker_);
|
|
267
|
+
if (!platform_.checkLocalNetworkAccess) {
|
|
268
|
+
// Nothing to grant on this platform
|
|
269
|
+
promise.resolve(ZeroconfAccessResult{std::string("granted"), std::nullopt});
|
|
270
|
+
return promise;
|
|
271
|
+
}
|
|
272
|
+
platform_.checkLocalNetworkAccess(
|
|
273
|
+
type,
|
|
274
|
+
timeout,
|
|
275
|
+
[promise](const std::string &status) mutable { promise.resolve(ZeroconfAccessResult{status, std::nullopt}); },
|
|
276
|
+
[promise](const rnzeroconf::Error &error) mutable { promise.resolve(ZeroconfAccessResult{std::nullopt, ToJs(error)}); });
|
|
277
|
+
return promise;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
} // namespace facebook::react
|