react-native-zeroconf 0.17.2 → 0.17.3
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/android/build.gradle +4 -0
- package/android/src/main/java/com/github/druk/dnssd/DNSSD.java +61 -30
- package/android/src/main/java/com/github/druk/dnssd/DNSSDEmbedded.java +103 -40
- package/android/src/main/jni/JNISupport.c +164 -83
- 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 +3 -3
- package/package.json +2 -1
package/android/build.gradle
CHANGED
|
@@ -13,6 +13,8 @@ android {
|
|
|
13
13
|
targetSdkVersion safeExtGet('targetSdkVersion', 34)
|
|
14
14
|
versionCode 1
|
|
15
15
|
versionName "1.0"
|
|
16
|
+
// Instrumented tests (android/src/androidTest), see docs/Contributing.md
|
|
17
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
16
18
|
|
|
17
19
|
ndk {
|
|
18
20
|
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
|
@@ -42,4 +44,6 @@ repositories {
|
|
|
42
44
|
|
|
43
45
|
dependencies {
|
|
44
46
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
|
|
47
|
+
androidTestImplementation 'androidx.test:runner:1.6.2'
|
|
48
|
+
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
|
45
49
|
}
|
|
@@ -106,6 +106,37 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
106
106
|
this.serviceTimeout = serviceTimeout;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// The embedded responder can answer before the call that starts an operation has returned, from its
|
|
110
|
+
// own thread or from inside the call. The operation is assigned under the monitor of its array while
|
|
111
|
+
// that call runs, and the callbacks posted to the main thread take the monitor first, so they wait for
|
|
112
|
+
// the call to return. If it threw, there is no operation and the callback is dropped.
|
|
113
|
+
|
|
114
|
+
private interface Start<T> {
|
|
115
|
+
T start() throws DNSSDException;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private interface OperationCallback<T> {
|
|
119
|
+
void run(T operation);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private static <T> void start(T[] operation, Start<T> start) throws DNSSDException {
|
|
123
|
+
synchronized (operation) {
|
|
124
|
+
operation[0] = start.start();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private <T> void postWith(final T[] operation, final OperationCallback<T> callback) {
|
|
129
|
+
handler.post(() -> {
|
|
130
|
+
T started;
|
|
131
|
+
synchronized (operation) {
|
|
132
|
+
started = operation[0];
|
|
133
|
+
}
|
|
134
|
+
if (started != null) {
|
|
135
|
+
callback.run(started);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
109
140
|
/** Browse for instances of a service.<P>
|
|
110
141
|
|
|
111
142
|
Note: browsing consumes network bandwidth. Call {@link InternalDNSSDService#stop} when you have finished browsing.<P>
|
|
@@ -139,13 +170,13 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
139
170
|
public DNSSDService browse(int flags, int ifIndex, String regType, String domain, final BrowseListener listener) throws DNSSDException {
|
|
140
171
|
onServiceStarting();
|
|
141
172
|
final InternalDNSSDService[] services = new InternalDNSSDService[1];
|
|
142
|
-
services
|
|
173
|
+
start(services, () -> new InternalDNSSDService(this, InternalDNSSD.browse(flags, ifIndex, regType, domain, new InternalBrowseListener() {
|
|
143
174
|
@Override
|
|
144
175
|
public void serviceFound(final DNSSDService browser, final int flags, final int ifIndex, final byte[] serviceName, final byte[] regType, final byte[] domain) {
|
|
145
176
|
final String serviceNameStr = new String(serviceName, UTF_8);
|
|
146
177
|
final String regTypeStr = new String(regType, UTF_8);
|
|
147
178
|
final String domainStr = new String(domain, UTF_8);
|
|
148
|
-
|
|
179
|
+
postWith(services, operation -> listener.serviceFound(operation, flags, ifIndex, serviceNameStr, regTypeStr, domainStr));
|
|
149
180
|
}
|
|
150
181
|
|
|
151
182
|
@Override
|
|
@@ -153,14 +184,14 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
153
184
|
final String serviceNameStr = new String(serviceName, UTF_8);
|
|
154
185
|
final String regTypeStr = new String(regType, UTF_8);
|
|
155
186
|
final String domainStr = new String(domain, UTF_8);
|
|
156
|
-
|
|
187
|
+
postWith(services, operation -> listener.serviceLost(operation, flags, ifIndex, serviceNameStr, regTypeStr, domainStr));
|
|
157
188
|
}
|
|
158
189
|
|
|
159
190
|
@Override
|
|
160
191
|
public void operationFailed(final DNSSDService service, final int errorCode) {
|
|
161
|
-
|
|
192
|
+
postWith(services, operation -> listener.operationFailed(operation, errorCode));
|
|
162
193
|
}
|
|
163
|
-
}));
|
|
194
|
+
})));
|
|
164
195
|
return services[0];
|
|
165
196
|
|
|
166
197
|
}
|
|
@@ -229,28 +260,28 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
229
260
|
|
|
230
261
|
final Runnable timeoutRunnable = () -> services[0].stop();
|
|
231
262
|
|
|
232
|
-
services
|
|
263
|
+
start(services, () -> new InternalDNSSDService(this, InternalDNSSD.resolve(flags, ifIndex, serviceName, regType, domain, new InternalResolveListener() {
|
|
233
264
|
@Override
|
|
234
265
|
public void serviceResolved(final DNSSDService resolver, final int flags, final int ifIndex, byte[] fullName, byte[] hostName, final int port, TXTRecord txtRecord) {
|
|
235
266
|
final String fullNameStr = new String(fullName, UTF_8);
|
|
236
267
|
final String hostNameStr = new String(hostName, UTF_8);
|
|
237
268
|
final Map<String, String> record = parseTXTRecords(txtRecord);
|
|
238
269
|
handler.removeCallbacks(timeoutRunnable);
|
|
239
|
-
|
|
240
|
-
listener.serviceResolved(
|
|
241
|
-
|
|
270
|
+
postWith(services, operation -> {
|
|
271
|
+
listener.serviceResolved(operation, flags, ifIndex, fullNameStr, hostNameStr, port, record);
|
|
272
|
+
operation.stop();
|
|
242
273
|
});
|
|
243
274
|
}
|
|
244
275
|
|
|
245
276
|
@Override
|
|
246
277
|
public void operationFailed(final DNSSDService service, final int errorCode) {
|
|
247
278
|
handler.removeCallbacks(timeoutRunnable);
|
|
248
|
-
|
|
249
|
-
listener.operationFailed(
|
|
250
|
-
|
|
279
|
+
postWith(services, operation -> {
|
|
280
|
+
listener.operationFailed(operation, errorCode);
|
|
281
|
+
operation.stop();
|
|
251
282
|
});
|
|
252
283
|
}
|
|
253
|
-
}));
|
|
284
|
+
})));
|
|
254
285
|
|
|
255
286
|
handler.postDelayed(timeoutRunnable, serviceTimeout);
|
|
256
287
|
return services[0];
|
|
@@ -313,7 +344,7 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
313
344
|
final RegisterListener listener) throws DNSSDException {
|
|
314
345
|
onServiceStarting();
|
|
315
346
|
final DNSSDRegistration[] services = new DNSSDRegistration[1];
|
|
316
|
-
services
|
|
347
|
+
start(services, () -> new InternalDNSSDRegistration(this, InternalDNSSD.register(flags, ifIndex, serviceName, regType, domain, host, port, txtRecord,
|
|
317
348
|
new InternalRegisterListener() {
|
|
318
349
|
|
|
319
350
|
@Override
|
|
@@ -321,14 +352,14 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
321
352
|
final String serviceNameStr = new String(serviceName, UTF_8);
|
|
322
353
|
final String regTypeStr = new String(regType, UTF_8);
|
|
323
354
|
final String domainStr = new String(domain, UTF_8);
|
|
324
|
-
|
|
355
|
+
postWith(services, operation -> listener.serviceRegistered(operation, flags, serviceNameStr, regTypeStr, domainStr));
|
|
325
356
|
}
|
|
326
357
|
|
|
327
358
|
@Override
|
|
328
359
|
public void operationFailed(DNSSDService service, final int errorCode) {
|
|
329
|
-
|
|
360
|
+
postWith(services, operation -> listener.operationFailed(operation, errorCode));
|
|
330
361
|
}
|
|
331
|
-
}));
|
|
362
|
+
})));
|
|
332
363
|
return services[0];
|
|
333
364
|
}
|
|
334
365
|
|
|
@@ -447,15 +478,15 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
447
478
|
|
|
448
479
|
final Runnable timeoutRunnable = () -> services[0].stop();
|
|
449
480
|
|
|
450
|
-
services
|
|
481
|
+
start(services, () -> new InternalDNSSDService(this, InternalDNSSD.queryRecord(flags, ifIndex, serviceName, rrtype, rrclass, new InternalQueryListener() {
|
|
451
482
|
@Override
|
|
452
483
|
public void queryAnswered(DNSSDService query, final int flags, final int ifIndex, byte[] fullName, final int rrtype, final int rrclass, byte[] rdata, final int ttl) {
|
|
453
484
|
final String fullNameStr = new String(fullName, UTF_8);
|
|
454
485
|
handler.removeCallbacks(timeoutRunnable);
|
|
455
|
-
|
|
456
|
-
listener.queryAnswered(
|
|
486
|
+
postWith(services, operation -> {
|
|
487
|
+
listener.queryAnswered(operation, flags, ifIndex, fullNameStr, rrtype, rrclass, rdata, ttl);
|
|
457
488
|
if (autoStop) {
|
|
458
|
-
|
|
489
|
+
operation.stop();
|
|
459
490
|
}
|
|
460
491
|
});
|
|
461
492
|
}
|
|
@@ -463,12 +494,12 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
463
494
|
@Override
|
|
464
495
|
public void operationFailed(DNSSDService service, final int errorCode) {
|
|
465
496
|
handler.removeCallbacks(timeoutRunnable);
|
|
466
|
-
|
|
467
|
-
listener.operationFailed(
|
|
468
|
-
|
|
497
|
+
postWith(services, operation -> {
|
|
498
|
+
listener.operationFailed(operation, errorCode);
|
|
499
|
+
operation.stop();
|
|
469
500
|
});
|
|
470
501
|
}
|
|
471
|
-
}));
|
|
502
|
+
})));
|
|
472
503
|
|
|
473
504
|
if (autoStop) {
|
|
474
505
|
handler.postDelayed(timeoutRunnable, serviceTimeout);
|
|
@@ -503,24 +534,24 @@ public abstract class DNSSD implements InternalDNSSDService.DnssdServiceListener
|
|
|
503
534
|
public DNSSDService enumerateDomains(int flags, int ifIndex, final DomainListener listener) throws DNSSDException {
|
|
504
535
|
onServiceStarting();
|
|
505
536
|
final DNSSDService[] services = new DNSSDService[1];
|
|
506
|
-
services
|
|
537
|
+
start(services, () -> new InternalDNSSDService(this, InternalDNSSD.enumerateDomains(flags, ifIndex, new InternalDomainListener() {
|
|
507
538
|
@Override
|
|
508
539
|
public void domainFound(DNSSDService domainEnum, final int flags, final int ifIndex, byte[] domain) {
|
|
509
540
|
final String domainStr = new String(domain, UTF_8);
|
|
510
|
-
|
|
541
|
+
postWith(services, operation -> listener.domainFound(operation, flags, ifIndex, domainStr));
|
|
511
542
|
}
|
|
512
543
|
|
|
513
544
|
@Override
|
|
514
545
|
public void domainLost(DNSSDService domainEnum, final int flags, final int ifIndex, byte[] domain) {
|
|
515
546
|
final String domainStr = new String(domain, UTF_8);
|
|
516
|
-
|
|
547
|
+
postWith(services, operation -> listener.domainLost(operation, flags, ifIndex, domainStr));
|
|
517
548
|
}
|
|
518
549
|
|
|
519
550
|
@Override
|
|
520
551
|
public void operationFailed(final DNSSDService service, final int errorCode) {
|
|
521
|
-
|
|
552
|
+
postWith(services, operation -> listener.operationFailed(operation, errorCode));
|
|
522
553
|
}
|
|
523
|
-
}));
|
|
554
|
+
})));
|
|
524
555
|
return services[0];
|
|
525
556
|
}
|
|
526
557
|
|
|
@@ -23,6 +23,10 @@ import android.util.Log;
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* DNSSD implementation running the embedded mDNSResponder {@link InternalDNSSD}
|
|
26
|
+
*
|
|
27
|
+
* The responder's event loop runs on its own thread, started by the first operation and stopped
|
|
28
|
+
* a while after the last one ended. Operations start and stop on arbitrary threads, so the
|
|
29
|
+
* lifecycle state below is guarded by the class monitor.
|
|
26
30
|
*/
|
|
27
31
|
public class DNSSDEmbedded extends DNSSD {
|
|
28
32
|
|
|
@@ -31,9 +35,11 @@ public class DNSSDEmbedded extends DNSSD {
|
|
|
31
35
|
private static final String TAG = "DNSSDEmbedded";
|
|
32
36
|
private final long mStopTimerDelay;
|
|
33
37
|
private final Handler handler = new Handler(Looper.getMainLooper());
|
|
34
|
-
private
|
|
35
|
-
private
|
|
36
|
-
private
|
|
38
|
+
private final ExitTimer exitTimer;
|
|
39
|
+
private Thread mThread; // guarded by DNSSDEmbedded.class
|
|
40
|
+
private volatile boolean isStarted = false; // the loop is running (set by the loop thread)
|
|
41
|
+
private volatile boolean isExiting = false; // nativeExit() was called, the thread is on its way out
|
|
42
|
+
private int serviceCount = 0; // guarded by DNSSDEmbedded.class
|
|
37
43
|
|
|
38
44
|
public DNSSDEmbedded(Context context) {
|
|
39
45
|
this(context, DEFAULT_STOP_TIMER_DELAY);
|
|
@@ -42,6 +48,35 @@ public class DNSSDEmbedded extends DNSSD {
|
|
|
42
48
|
public DNSSDEmbedded(Context context, long stopTimerDelay) {
|
|
43
49
|
super(context, "jdns_sd_embedded");
|
|
44
50
|
mStopTimerDelay = stopTimerDelay;
|
|
51
|
+
exitTimer = new ExitTimer(handler, stopTimerDelay, this::exitIfIdle);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Stops the responder a while after the last operation ended, unless another one starts first.
|
|
56
|
+
* The same Runnable is posted and removed: evaluating a method reference at two call sites
|
|
57
|
+
* gives two objects, so posting one and removing the other would never cancel anything.
|
|
58
|
+
*/
|
|
59
|
+
static final class ExitTimer {
|
|
60
|
+
private final Handler handler;
|
|
61
|
+
private final long delayMillis;
|
|
62
|
+
private final Runnable exit;
|
|
63
|
+
|
|
64
|
+
ExitTimer(Handler handler, long delayMillis, Runnable exit) {
|
|
65
|
+
this.handler = handler;
|
|
66
|
+
this.delayMillis = delayMillis;
|
|
67
|
+
this.exit = exit;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The last operation stopped: exit after the delay. */
|
|
71
|
+
void schedule() {
|
|
72
|
+
handler.removeCallbacks(exit);
|
|
73
|
+
handler.postDelayed(exit, delayMillis);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** An operation is starting: the responder stays up. */
|
|
77
|
+
void cancel() {
|
|
78
|
+
handler.removeCallbacks(exit);
|
|
79
|
+
}
|
|
45
80
|
}
|
|
46
81
|
|
|
47
82
|
static native int nativeInit();
|
|
@@ -57,40 +92,52 @@ public class DNSSDEmbedded extends DNSSD {
|
|
|
57
92
|
* Note: This method will block thread until DNS-SD initialization finish.
|
|
58
93
|
*/
|
|
59
94
|
public void init() {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (mThread != null && mThread.isAlive()) {
|
|
63
|
-
Log.i(TAG, "already started");
|
|
64
|
-
waitUntilStarted();
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
isStarted = false;
|
|
95
|
+
synchronized (DNSSDEmbedded.class) {
|
|
96
|
+
exitTimer.cancel();
|
|
69
97
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
int err = nativeInit();
|
|
75
|
-
synchronized (DNSSDEmbedded.class) {
|
|
76
|
-
isStarted = true;
|
|
77
|
-
DNSSDEmbedded.class.notifyAll();
|
|
78
|
-
}
|
|
79
|
-
if (err != 0) {
|
|
80
|
-
Log.e(TAG, "error: " + err);
|
|
98
|
+
if (mThread != null && mThread.isAlive()) {
|
|
99
|
+
if (!isExiting) {
|
|
100
|
+
Log.i(TAG, "already started");
|
|
101
|
+
waitUntilStarted();
|
|
81
102
|
return;
|
|
82
103
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
104
|
+
// The exit timer fired just before this operation: let the thread finish, then start afresh
|
|
105
|
+
Log.i(TAG, "restarting");
|
|
106
|
+
try {
|
|
107
|
+
mThread.join();
|
|
108
|
+
} catch (InterruptedException e) {
|
|
109
|
+
Log.e(TAG, "init interrupted while waiting for the previous loop: ", e);
|
|
110
|
+
}
|
|
87
111
|
}
|
|
88
|
-
};
|
|
89
|
-
mThread.setPriority(Thread.MAX_PRIORITY);
|
|
90
|
-
mThread.setName("DNS-SDEmbedded");
|
|
91
|
-
mThread.start();
|
|
92
112
|
|
|
93
|
-
|
|
113
|
+
isStarted = false;
|
|
114
|
+
isExiting = false;
|
|
115
|
+
|
|
116
|
+
InternalDNSSD.getInstance();
|
|
117
|
+
mThread = new Thread() {
|
|
118
|
+
public void run() {
|
|
119
|
+
Log.i(TAG, "init");
|
|
120
|
+
int err = nativeInit();
|
|
121
|
+
synchronized (DNSSDEmbedded.class) {
|
|
122
|
+
isStarted = true;
|
|
123
|
+
DNSSDEmbedded.class.notifyAll();
|
|
124
|
+
}
|
|
125
|
+
if (err != 0) {
|
|
126
|
+
Log.e(TAG, "error: " + err);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
Log.i(TAG, "start");
|
|
130
|
+
int ret = nativeLoop();
|
|
131
|
+
isStarted = false;
|
|
132
|
+
Log.i(TAG, "finish with code: " + ret);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
mThread.setPriority(Thread.MAX_PRIORITY);
|
|
136
|
+
mThread.setName("DNS-SDEmbedded");
|
|
137
|
+
mThread.start();
|
|
138
|
+
|
|
139
|
+
waitUntilStarted();
|
|
140
|
+
}
|
|
94
141
|
}
|
|
95
142
|
|
|
96
143
|
/**
|
|
@@ -101,7 +148,19 @@ public class DNSSDEmbedded extends DNSSD {
|
|
|
101
148
|
public void exit() {
|
|
102
149
|
synchronized (DNSSDEmbedded.class) {
|
|
103
150
|
Log.i(TAG, "post exit");
|
|
104
|
-
|
|
151
|
+
exitTimer.schedule();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Runs on the main thread when the timer fires; an operation may have started since it was scheduled
|
|
156
|
+
private void exitIfIdle() {
|
|
157
|
+
synchronized (DNSSDEmbedded.class) {
|
|
158
|
+
if (serviceCount != 0 || isExiting || mThread == null || !mThread.isAlive()) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
Log.i(TAG, "exit");
|
|
162
|
+
isExiting = true;
|
|
163
|
+
nativeExit();
|
|
105
164
|
}
|
|
106
165
|
}
|
|
107
166
|
|
|
@@ -119,17 +178,21 @@ public class DNSSDEmbedded extends DNSSD {
|
|
|
119
178
|
|
|
120
179
|
@Override
|
|
121
180
|
public void onServiceStarting() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
181
|
+
synchronized (DNSSDEmbedded.class) {
|
|
182
|
+
super.onServiceStarting();
|
|
183
|
+
this.init();
|
|
184
|
+
serviceCount++;
|
|
185
|
+
}
|
|
125
186
|
}
|
|
126
187
|
|
|
127
188
|
@Override
|
|
128
189
|
public void onServiceStopped() {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
190
|
+
synchronized (DNSSDEmbedded.class) {
|
|
191
|
+
super.onServiceStopped();
|
|
192
|
+
serviceCount--;
|
|
193
|
+
if (serviceCount == 0) {
|
|
194
|
+
this.exit();
|
|
195
|
+
}
|
|
133
196
|
}
|
|
134
197
|
}
|
|
135
198
|
}
|
|
@@ -107,14 +107,26 @@ struct OpContext
|
|
|
107
107
|
|
|
108
108
|
//For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
|
|
109
109
|
#if AUTO_CALLBACKS
|
|
110
|
-
JNIEnv *pLoopEnv = NULL;
|
|
110
|
+
JNIEnv *pLoopEnv = NULL; // The event loop thread's env, the fallback when the current thread's is unavailable
|
|
111
|
+
static JavaVM *gJavaVM = NULL;
|
|
111
112
|
#endif
|
|
112
113
|
|
|
113
114
|
#ifdef EMBEDDED
|
|
114
115
|
int init();
|
|
115
116
|
int loop();
|
|
116
117
|
void stopLoop();
|
|
118
|
+
void lockCore();
|
|
119
|
+
void unlockCore();
|
|
120
|
+
// The embedded shim reads core state (the interface list, the host name) before mDNS core
|
|
121
|
+
// takes its own lock, so every call into it is made under the core lock. It is recursive.
|
|
122
|
+
#define LOCK_CORE() lockCore()
|
|
123
|
+
#define UNLOCK_CORE() unlockCore()
|
|
124
|
+
#else
|
|
125
|
+
#define LOCK_CORE() do { } while (0)
|
|
126
|
+
#define UNLOCK_CORE() do { } while (0)
|
|
127
|
+
#endif
|
|
117
128
|
|
|
129
|
+
#ifdef EMBEDDED
|
|
118
130
|
JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_DNSSDEmbedded_nativeInit( JNIEnv *pEnv, jclass cls)
|
|
119
131
|
{
|
|
120
132
|
pLoopEnv = pEnv;
|
|
@@ -140,12 +152,8 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleDNSSD_InitLibrary( JNIEnv
|
|
|
140
152
|
return kDNSServiceErr_Incompatible;
|
|
141
153
|
|
|
142
154
|
#if AUTO_CALLBACKS
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
|
|
147
|
-
// return kDNSServiceErr_BadState;
|
|
148
|
-
// }
|
|
155
|
+
if ( gJavaVM == NULL && 0 != (*pEnv)->GetJavaVM( pEnv, &gJavaVM))
|
|
156
|
+
return kDNSServiceErr_BadState;
|
|
149
157
|
#endif
|
|
150
158
|
|
|
151
159
|
// Set AppleDNSSD.hasAutoCallbacks
|
|
@@ -180,13 +188,18 @@ static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
|
|
|
180
188
|
#if AUTO_CALLBACKS
|
|
181
189
|
static void SetupCallbackState( JNIEnv **ppEnv)
|
|
182
190
|
{
|
|
183
|
-
|
|
184
|
-
//
|
|
191
|
+
// Callbacks usually come from the event loop thread, but mDNS core also calls back from inside
|
|
192
|
+
// an API call, on the client's thread: a local-only registration is acknowledged inside
|
|
193
|
+
// DNSServiceRegister(). A JNIEnv belongs to one thread, so use the current thread's.
|
|
194
|
+
JNIEnv *pEnv = NULL;
|
|
195
|
+
if ( gJavaVM != NULL && JNI_OK == (*gJavaVM)->GetEnv( gJavaVM, (void**) &pEnv, JNI_VERSION_1_6) && pEnv != NULL)
|
|
196
|
+
(*ppEnv) = pEnv;
|
|
197
|
+
else
|
|
198
|
+
(*ppEnv) = pLoopEnv;
|
|
185
199
|
}
|
|
186
200
|
|
|
187
201
|
static void TeardownCallbackState( void )
|
|
188
202
|
{
|
|
189
|
-
//(*gJavaVM)->DetachCurrentThread( gJavaVM);
|
|
190
203
|
}
|
|
191
204
|
|
|
192
205
|
#else // AUTO_CALLBACKS
|
|
@@ -248,6 +261,13 @@ JNIEXPORT void JNICALL Java_com_github_druk_dnssd_AppleService_HaltOperation( JN
|
|
|
248
261
|
OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
|
|
249
262
|
if ( pContext != NULL)
|
|
250
263
|
{
|
|
264
|
+
// The embedded responder delivers callbacks from its own thread and may be in
|
|
265
|
+
// the middle of one for this very operation (an answer with several records
|
|
266
|
+
// invokes the callback once per record). DNSServiceRefDeallocate() takes the
|
|
267
|
+
// core lock itself; holding it here too keeps the weak refs and the free() in
|
|
268
|
+
// the same critical section. Consequently a Java callback running on the loop
|
|
269
|
+
// thread must never block on a thread that may be in here (the main thread).
|
|
270
|
+
LOCK_CORE();
|
|
251
271
|
// MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate()
|
|
252
272
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, 0);
|
|
253
273
|
if ( pContext->ServiceRef != NULL)
|
|
@@ -256,6 +276,7 @@ JNIEXPORT void JNICALL Java_com_github_druk_dnssd_AppleService_HaltOperation( JN
|
|
|
256
276
|
(*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
|
|
257
277
|
(*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
|
|
258
278
|
free( pContext);
|
|
279
|
+
UNLOCK_CORE();
|
|
259
280
|
}
|
|
260
281
|
}
|
|
261
282
|
}
|
|
@@ -355,29 +376,36 @@ static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServic
|
|
|
355
376
|
|
|
356
377
|
SetupCallbackState( &pContext->Env);
|
|
357
378
|
|
|
358
|
-
|
|
379
|
+
// Copies: the Java callback may stop this operation, after which pContext is freed.
|
|
380
|
+
JNIEnv *env = pContext->Env;
|
|
381
|
+
jobject javaObj = pContext->JavaObj;
|
|
382
|
+
jobject clientRef = pContext->ClientObj;
|
|
383
|
+
jmethodID callback = pContext->Callback;
|
|
384
|
+
jmethodID callback2 = pContext->Callback2;
|
|
385
|
+
|
|
386
|
+
jobject clientObj = (*env)->NewLocalRef(env, clientRef);
|
|
359
387
|
|
|
360
|
-
if ( clientObj != NULL &&
|
|
388
|
+
if ( clientObj != NULL && callback != NULL)
|
|
361
389
|
{
|
|
362
390
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
363
391
|
{
|
|
364
|
-
jbyteArray jServiceName = (*
|
|
365
|
-
(*
|
|
366
|
-
jbyteArray jRegType = (*
|
|
367
|
-
(*
|
|
368
|
-
jbyteArray jReplyDomain = (*
|
|
369
|
-
(*
|
|
370
|
-
(*
|
|
371
|
-
( flags & kDNSServiceFlagsAdd) != 0 ?
|
|
372
|
-
|
|
373
|
-
(*
|
|
374
|
-
(*
|
|
375
|
-
(*
|
|
392
|
+
jbyteArray jServiceName = (*env)->NewByteArray(env, (jsize)strlen(serviceName));
|
|
393
|
+
(*env)->SetByteArrayRegion (env, jServiceName, 0, (jsize)strlen(serviceName), (const jbyte *) serviceName);
|
|
394
|
+
jbyteArray jRegType = (*env)->NewByteArray(env, (jsize)strlen(regtype));
|
|
395
|
+
(*env)->SetByteArrayRegion (env, jRegType, 0, (jsize)strlen(regtype), (const jbyte *) regtype);
|
|
396
|
+
jbyteArray jReplyDomain = (*env)->NewByteArray(env, (jsize)strlen(replyDomain));
|
|
397
|
+
(*env)->SetByteArrayRegion (env, jReplyDomain, 0, (jsize)strlen(replyDomain), (const jbyte *) replyDomain);
|
|
398
|
+
(*env)->CallVoidMethod( env, clientObj,
|
|
399
|
+
( flags & kDNSServiceFlagsAdd) != 0 ? callback : callback2,
|
|
400
|
+
javaObj, flags, interfaceIndex, jServiceName, jRegType, jReplyDomain);
|
|
401
|
+
(*env)->DeleteLocalRef( env, jServiceName);
|
|
402
|
+
(*env)->DeleteLocalRef( env, jRegType);
|
|
403
|
+
(*env)->DeleteLocalRef( env, jReplyDomain);
|
|
376
404
|
}
|
|
377
405
|
else
|
|
378
|
-
ReportError(
|
|
406
|
+
ReportError( env, clientObj, javaObj, errorCode);
|
|
379
407
|
|
|
380
|
-
(*
|
|
408
|
+
(*env)->DeleteLocalRef(env, clientObj);
|
|
381
409
|
}
|
|
382
410
|
|
|
383
411
|
TeardownCallbackState();
|
|
@@ -406,7 +434,9 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleBrowser_CreateBrowser( JN
|
|
|
406
434
|
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
|
|
407
435
|
"serviceLost", "(Lcom/github/druk/dnssd/DNSSDService;II[B[B[B)V");
|
|
408
436
|
|
|
437
|
+
LOCK_CORE();
|
|
409
438
|
err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
|
|
439
|
+
UNLOCK_CORE();
|
|
410
440
|
if ( err == kDNSServiceErr_NoError)
|
|
411
441
|
{
|
|
412
442
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
@@ -435,11 +465,17 @@ static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServi
|
|
|
435
465
|
|
|
436
466
|
SetupCallbackState( &pContext->Env);
|
|
437
467
|
|
|
438
|
-
|
|
439
|
-
|
|
468
|
+
// Copies: the Java callback may stop this operation, after which pContext is freed.
|
|
469
|
+
JNIEnv *env = pContext->Env;
|
|
470
|
+
jobject javaObj = pContext->JavaObj;
|
|
471
|
+
jobject clientRef = pContext->ClientObj;
|
|
472
|
+
jmethodID callback = pContext->Callback;
|
|
440
473
|
|
|
441
|
-
|
|
442
|
-
|
|
474
|
+
txtCls = (*env)->FindClass( env, "com/github/druk/dnssd/TXTRecord");
|
|
475
|
+
txtCtor = (*env)->GetMethodID( env, txtCls, "<init>", "([B)V");
|
|
476
|
+
|
|
477
|
+
if ( clientRef != NULL && callback != NULL && txtCtor != NULL &&
|
|
478
|
+
NULL != ( txtBytes = (*env)->NewByteArray( env, txtLen)))
|
|
443
479
|
{
|
|
444
480
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
445
481
|
{
|
|
@@ -448,26 +484,26 @@ static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServi
|
|
|
448
484
|
port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
|
|
449
485
|
|
|
450
486
|
// Initialize txtBytes with contents of txtRecord
|
|
451
|
-
pBytes = (*
|
|
487
|
+
pBytes = (*env)->GetByteArrayElements( env, txtBytes, NULL);
|
|
452
488
|
memcpy( pBytes, txtRecord, txtLen);
|
|
453
|
-
(*
|
|
489
|
+
(*env)->ReleaseByteArrayElements( env, txtBytes, pBytes, JNI_COMMIT);
|
|
454
490
|
|
|
455
491
|
// Construct txtObj with txtBytes
|
|
456
|
-
txtObj = (*
|
|
457
|
-
(*
|
|
458
|
-
|
|
459
|
-
jbyteArray jFullName = (*
|
|
460
|
-
(*
|
|
461
|
-
jbyteArray jHostTarget = (*
|
|
462
|
-
(*
|
|
463
|
-
(*
|
|
464
|
-
|
|
465
|
-
(*
|
|
466
|
-
(*
|
|
467
|
-
(*
|
|
492
|
+
txtObj = (*env)->NewObject( env, txtCls, txtCtor, txtBytes);
|
|
493
|
+
(*env)->DeleteLocalRef( env, txtBytes);
|
|
494
|
+
|
|
495
|
+
jbyteArray jFullName = (*env)->NewByteArray(env, (jsize)strlen(fullname));
|
|
496
|
+
(*env)->SetByteArrayRegion (env, jFullName, 0, (jsize)strlen(fullname), (const jbyte *) fullname);
|
|
497
|
+
jbyteArray jHostTarget = (*env)->NewByteArray(env, (jsize)strlen(hosttarget));
|
|
498
|
+
(*env)->SetByteArrayRegion (env, jHostTarget, 0, (jsize)strlen(hosttarget), (const jbyte *) hosttarget);
|
|
499
|
+
(*env)->CallVoidMethod( env, clientRef, callback,
|
|
500
|
+
javaObj, flags, interfaceIndex, jFullName, jHostTarget, port, txtObj);
|
|
501
|
+
(*env)->DeleteLocalRef( env, jFullName);
|
|
502
|
+
(*env)->DeleteLocalRef( env, jHostTarget);
|
|
503
|
+
(*env)->DeleteLocalRef( env, txtObj);
|
|
468
504
|
}
|
|
469
505
|
else
|
|
470
|
-
ReportError(
|
|
506
|
+
ReportError( env, clientRef, javaObj, errorCode);
|
|
471
507
|
}
|
|
472
508
|
|
|
473
509
|
TeardownCallbackState();
|
|
@@ -493,8 +529,10 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleResolver_CreateResolver(
|
|
|
493
529
|
const char *regStr = SafeGetUTFChars( pEnv, regType);
|
|
494
530
|
const char *domainStr = SafeGetUTFChars( pEnv, domain);
|
|
495
531
|
|
|
532
|
+
LOCK_CORE();
|
|
496
533
|
err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
|
|
497
534
|
servStr, regStr, domainStr, ServiceResolveReply, pContext);
|
|
535
|
+
UNLOCK_CORE();
|
|
498
536
|
if ( err == kDNSServiceErr_NoError)
|
|
499
537
|
{
|
|
500
538
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
@@ -519,25 +557,31 @@ static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServ
|
|
|
519
557
|
|
|
520
558
|
SetupCallbackState( &pContext->Env);
|
|
521
559
|
|
|
522
|
-
|
|
560
|
+
// Copies: the Java callback may stop this operation, after which pContext is freed.
|
|
561
|
+
JNIEnv *env = pContext->Env;
|
|
562
|
+
jobject javaObj = pContext->JavaObj;
|
|
563
|
+
jobject clientRef = pContext->ClientObj;
|
|
564
|
+
jmethodID callback = pContext->Callback;
|
|
565
|
+
|
|
566
|
+
if ( clientRef != NULL && callback != NULL)
|
|
523
567
|
{
|
|
524
568
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
525
569
|
{
|
|
526
|
-
jbyteArray jServiceName = (*
|
|
527
|
-
(*
|
|
528
|
-
jbyteArray jRegType = (*
|
|
529
|
-
(*
|
|
530
|
-
jbyteArray jDomain = (*
|
|
531
|
-
(*
|
|
532
|
-
|
|
533
|
-
(*
|
|
534
|
-
|
|
535
|
-
(*
|
|
536
|
-
(*
|
|
537
|
-
(*
|
|
570
|
+
jbyteArray jServiceName = (*env)->NewByteArray(env, (jsize)strlen(serviceName));
|
|
571
|
+
(*env)->SetByteArrayRegion (env, jServiceName, 0, (jsize)strlen(serviceName), (const jbyte *) serviceName);
|
|
572
|
+
jbyteArray jRegType = (*env)->NewByteArray(env, (jsize)strlen(regType));
|
|
573
|
+
(*env)->SetByteArrayRegion (env, jRegType, 0, (jsize)strlen(regType), (const jbyte *) regType);
|
|
574
|
+
jbyteArray jDomain = (*env)->NewByteArray(env, (jsize)strlen(domain));
|
|
575
|
+
(*env)->SetByteArrayRegion (env, jDomain, 0, (jsize)strlen(domain), (const jbyte *) domain);
|
|
576
|
+
|
|
577
|
+
(*env)->CallVoidMethod( env, clientRef, callback,
|
|
578
|
+
javaObj, flags,jServiceName, jRegType, jDomain);
|
|
579
|
+
(*env)->DeleteLocalRef( env, jServiceName);
|
|
580
|
+
(*env)->DeleteLocalRef( env, jRegType);
|
|
581
|
+
(*env)->DeleteLocalRef( env, jDomain);
|
|
538
582
|
}
|
|
539
583
|
else
|
|
540
|
-
ReportError(
|
|
584
|
+
ReportError( env, clientRef, javaObj, errorCode);
|
|
541
585
|
}
|
|
542
586
|
TeardownCallbackState();
|
|
543
587
|
}
|
|
@@ -579,9 +623,11 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleRegistration_BeginRegiste
|
|
|
579
623
|
pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
|
|
580
624
|
numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
|
|
581
625
|
|
|
626
|
+
LOCK_CORE();
|
|
582
627
|
err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
|
|
583
628
|
domainStr, hostStr, portBits,
|
|
584
629
|
numBytes, pBytes, ServiceRegisterReply, pContext);
|
|
630
|
+
UNLOCK_CORE();
|
|
585
631
|
if ( err == kDNSServiceErr_NoError)
|
|
586
632
|
{
|
|
587
633
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
@@ -622,7 +668,9 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleRegistration_AddRecord( J
|
|
|
622
668
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
|
|
623
669
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
|
|
624
670
|
|
|
671
|
+
LOCK_CORE();
|
|
625
672
|
err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
|
|
673
|
+
UNLOCK_CORE();
|
|
626
674
|
if ( err == kDNSServiceErr_NoError)
|
|
627
675
|
{
|
|
628
676
|
(*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
|
|
@@ -662,7 +710,9 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleDNSRecord_Update( JNIEnv
|
|
|
662
710
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
|
|
663
711
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
|
|
664
712
|
|
|
713
|
+
LOCK_CORE();
|
|
665
714
|
err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
|
|
715
|
+
UNLOCK_CORE();
|
|
666
716
|
|
|
667
717
|
if ( pBytes != NULL)
|
|
668
718
|
(*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
|
|
@@ -692,7 +742,9 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleDNSRecord_Remove( JNIEnv
|
|
|
692
742
|
if ( pContext == NULL || pContext->ServiceRef == NULL)
|
|
693
743
|
return kDNSServiceErr_BadParam;
|
|
694
744
|
|
|
745
|
+
LOCK_CORE();
|
|
695
746
|
err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
|
|
747
|
+
UNLOCK_CORE();
|
|
696
748
|
|
|
697
749
|
return err;
|
|
698
750
|
}
|
|
@@ -712,7 +764,9 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleRecordRegistrar_CreateCon
|
|
|
712
764
|
|
|
713
765
|
if ( pContext != NULL)
|
|
714
766
|
{
|
|
767
|
+
LOCK_CORE();
|
|
715
768
|
err = DNSServiceCreateConnection( &pContext->ServiceRef);
|
|
769
|
+
UNLOCK_CORE();
|
|
716
770
|
if ( err == kDNSServiceErr_NoError)
|
|
717
771
|
{
|
|
718
772
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
@@ -740,18 +794,24 @@ static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED,
|
|
|
740
794
|
|
|
741
795
|
SetupCallbackState( &pContext->Env);
|
|
742
796
|
|
|
743
|
-
|
|
797
|
+
// Copies: the Java callback may stop this operation, after which pContext is freed.
|
|
798
|
+
JNIEnv *env = pContext->Env;
|
|
799
|
+
jobject javaObj = pContext->JavaObj;
|
|
800
|
+
jobject clientRef = pContext->ClientObj;
|
|
801
|
+
jmethodID callback = pContext->Callback;
|
|
802
|
+
|
|
803
|
+
if ( clientRef != NULL && callback != NULL)
|
|
744
804
|
{
|
|
745
805
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
746
806
|
{
|
|
747
|
-
(*
|
|
807
|
+
(*env)->CallVoidMethod( env, clientRef, callback,
|
|
748
808
|
regEnvelope->RecordObj, flags);
|
|
749
809
|
}
|
|
750
810
|
else
|
|
751
|
-
ReportError(
|
|
811
|
+
ReportError( env, clientRef, javaObj, errorCode);
|
|
752
812
|
}
|
|
753
813
|
|
|
754
|
-
(*
|
|
814
|
+
(*env)->DeleteWeakGlobalRef( env, regEnvelope->RecordObj);
|
|
755
815
|
free( regEnvelope);
|
|
756
816
|
|
|
757
817
|
TeardownCallbackState();
|
|
@@ -787,9 +847,11 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleRecordRegistrar_RegisterR
|
|
|
787
847
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
|
|
788
848
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
|
|
789
849
|
|
|
850
|
+
LOCK_CORE();
|
|
790
851
|
err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex,
|
|
791
852
|
nameStr, rrType, rrClass, numBytes, pBytes, ttl,
|
|
792
853
|
RegisterRecordReply, regEnvelope);
|
|
854
|
+
UNLOCK_CORE();
|
|
793
855
|
|
|
794
856
|
if ( err == kDNSServiceErr_NoError)
|
|
795
857
|
{
|
|
@@ -822,25 +884,31 @@ static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSService
|
|
|
822
884
|
|
|
823
885
|
SetupCallbackState( &pContext->Env);
|
|
824
886
|
|
|
825
|
-
|
|
826
|
-
|
|
887
|
+
// Copies: the Java callback may stop this operation, after which pContext is freed.
|
|
888
|
+
JNIEnv *env = pContext->Env;
|
|
889
|
+
jobject javaObj = pContext->JavaObj;
|
|
890
|
+
jobject clientRef = pContext->ClientObj;
|
|
891
|
+
jmethodID callback = pContext->Callback;
|
|
892
|
+
|
|
893
|
+
if ( clientRef != NULL && callback != NULL &&
|
|
894
|
+
NULL != ( rDataObj = (*env)->NewByteArray( env, rdlen)))
|
|
827
895
|
{
|
|
828
896
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
829
897
|
{
|
|
830
898
|
// Initialize rDataObj with contents of rdata
|
|
831
|
-
pBytes = (*
|
|
899
|
+
pBytes = (*env)->GetByteArrayElements( env, rDataObj, NULL);
|
|
832
900
|
memcpy( pBytes, rdata, rdlen);
|
|
833
|
-
(*
|
|
834
|
-
|
|
835
|
-
jbyteArray jServiceName = (*
|
|
836
|
-
(*
|
|
837
|
-
(*
|
|
838
|
-
|
|
839
|
-
(*
|
|
840
|
-
(*
|
|
901
|
+
(*env)->ReleaseByteArrayElements( env, rDataObj, pBytes, JNI_COMMIT);
|
|
902
|
+
|
|
903
|
+
jbyteArray jServiceName = (*env)->NewByteArray(env, (jsize)strlen(serviceName));
|
|
904
|
+
(*env)->SetByteArrayRegion (env, jServiceName, 0, (jsize)strlen(serviceName), (const jbyte *) serviceName);
|
|
905
|
+
(*env)->CallVoidMethod( env, clientRef, callback,
|
|
906
|
+
javaObj, flags, interfaceIndex, jServiceName, rrtype, rrclass, rDataObj, ttl);
|
|
907
|
+
(*env)->DeleteLocalRef( env, jServiceName);
|
|
908
|
+
(*env)->DeleteLocalRef( env, rDataObj);
|
|
841
909
|
}
|
|
842
910
|
else
|
|
843
|
-
ReportError(
|
|
911
|
+
ReportError( env, clientRef, javaObj, errorCode);
|
|
844
912
|
}
|
|
845
913
|
TeardownCallbackState();
|
|
846
914
|
}
|
|
@@ -863,8 +931,10 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleQuery_CreateQuery( JNIEnv
|
|
|
863
931
|
{
|
|
864
932
|
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
|
|
865
933
|
|
|
934
|
+
LOCK_CORE();
|
|
866
935
|
err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
|
|
867
936
|
rrtype, rrclass, ServiceQueryReply, pContext);
|
|
937
|
+
UNLOCK_CORE();
|
|
868
938
|
if ( err == kDNSServiceErr_NoError)
|
|
869
939
|
{
|
|
870
940
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
@@ -886,19 +956,26 @@ static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFl
|
|
|
886
956
|
|
|
887
957
|
SetupCallbackState( &pContext->Env);
|
|
888
958
|
|
|
889
|
-
|
|
959
|
+
// Copies: the Java callback may stop this operation, after which pContext is freed.
|
|
960
|
+
JNIEnv *env = pContext->Env;
|
|
961
|
+
jobject javaObj = pContext->JavaObj;
|
|
962
|
+
jobject clientRef = pContext->ClientObj;
|
|
963
|
+
jmethodID callback = pContext->Callback;
|
|
964
|
+
jmethodID callback2 = pContext->Callback2;
|
|
965
|
+
|
|
966
|
+
if ( clientRef != NULL && callback != NULL)
|
|
890
967
|
{
|
|
891
968
|
if ( errorCode == kDNSServiceErr_NoError)
|
|
892
969
|
{
|
|
893
|
-
jbyteArray jReplyDomain = (*
|
|
894
|
-
(*
|
|
895
|
-
(*
|
|
896
|
-
( flags & kDNSServiceFlagsAdd) != 0 ?
|
|
897
|
-
|
|
898
|
-
(*
|
|
970
|
+
jbyteArray jReplyDomain = (*env)->NewByteArray(env, (jsize)strlen(replyDomain));
|
|
971
|
+
(*env)->SetByteArrayRegion (env, jReplyDomain, 0, (jsize)strlen(replyDomain), (const jbyte *) replyDomain);
|
|
972
|
+
(*env)->CallVoidMethod( env, clientRef,
|
|
973
|
+
( flags & kDNSServiceFlagsAdd) != 0 ? callback : callback2,
|
|
974
|
+
javaObj, flags, interfaceIndex, jReplyDomain);
|
|
975
|
+
(*env)->DeleteLocalRef( env, jReplyDomain);
|
|
899
976
|
}
|
|
900
977
|
else
|
|
901
|
-
ReportError(
|
|
978
|
+
ReportError( env, clientRef, javaObj, errorCode);
|
|
902
979
|
}
|
|
903
980
|
TeardownCallbackState();
|
|
904
981
|
}
|
|
@@ -923,8 +1000,10 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleDomainEnum_BeginEnum( JNI
|
|
|
923
1000
|
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
|
|
924
1001
|
"domainLost", "(Lcom/github/druk/dnssd/DNSSDService;II[B)V");
|
|
925
1002
|
|
|
1003
|
+
LOCK_CORE();
|
|
926
1004
|
err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
|
|
927
1005
|
DomainEnumReply, pContext);
|
|
1006
|
+
UNLOCK_CORE();
|
|
928
1007
|
if ( err == kDNSServiceErr_NoError)
|
|
929
1008
|
{
|
|
930
1009
|
(*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
|
|
@@ -973,7 +1052,9 @@ JNIEXPORT jint JNICALL Java_com_github_druk_dnssd_AppleDNSSD_ReconfirmRecord( JN
|
|
|
973
1052
|
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
|
|
974
1053
|
numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
|
|
975
1054
|
|
|
1055
|
+
LOCK_CORE();
|
|
976
1056
|
err = DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
|
|
1057
|
+
UNLOCK_CORE();
|
|
977
1058
|
|
|
978
1059
|
if ( pBytes != NULL)
|
|
979
1060
|
(*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
|
|
@@ -51,6 +51,7 @@ extern int daemon(int, int);
|
|
|
51
51
|
|
|
52
52
|
#include "mDNSEmbeddedAPI.h"
|
|
53
53
|
#include "mDNSPosix.h"
|
|
54
|
+
#include "DNSCommon.h" // mDNS_Lock / mDNS_Unlock, for Reconfigure()
|
|
54
55
|
#include "mDNSUNP.h" // For daemon()
|
|
55
56
|
#include "uds_daemon.h"
|
|
56
57
|
#include "PlatformCommon.h"
|
|
@@ -67,7 +68,7 @@ static domainname DynDNSHostname;
|
|
|
67
68
|
static CacheEntity gRRCache[RR_CACHE_SIZE];
|
|
68
69
|
static mDNS_PlatformSupport PlatformStorage;
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
volatile sig_atomic_t stopNow = 0; // Set from another thread by stopLoop()
|
|
71
72
|
|
|
72
73
|
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
|
|
73
74
|
{
|
|
@@ -101,8 +102,10 @@ static void Reconfigure(mDNS *m)
|
|
|
101
102
|
mDNSAddr DynDNSIP;
|
|
102
103
|
const mDNSAddr dummy = { mDNSAddrType_IPv4, { { { 1, 1, 1, 1 } } } };;
|
|
103
104
|
mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
|
|
105
|
+
mDNS_Lock(m); // mDNS_AddDNSServer() expects the lock to be held
|
|
104
106
|
if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
|
|
105
107
|
LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
|
|
108
|
+
mDNS_Unlock(m);
|
|
106
109
|
ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
|
|
107
110
|
mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
|
|
108
111
|
if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
|
|
@@ -263,7 +266,9 @@ int loop(){
|
|
|
263
266
|
mStatus err;
|
|
264
267
|
Reconfigure(&mDNSStorage);
|
|
265
268
|
|
|
269
|
+
mDNSPosixEmbeddedLoopStarting();
|
|
266
270
|
err = MainLoop(&mDNSStorage);
|
|
271
|
+
mDNSPosixEmbeddedLoopStopping();
|
|
267
272
|
|
|
268
273
|
LogMsg("%s stopping", mDNSResponderVersionString);
|
|
269
274
|
|
|
@@ -279,6 +284,19 @@ int loop(){
|
|
|
279
284
|
void stopLoop()
|
|
280
285
|
{
|
|
281
286
|
stopNow = 1;
|
|
287
|
+
mDNSPosixEmbeddedWakeLoop(); // It may be sleeping in select() until its next timer
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// For JNISupport.c: hold the core lock around work on an operation's data structures
|
|
291
|
+
// that must not interleave with the event loop thread (callbacks run on that thread).
|
|
292
|
+
void lockCore()
|
|
293
|
+
{
|
|
294
|
+
mDNSPlatformLock(&mDNSStorage);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
void unlockCore()
|
|
298
|
+
{
|
|
299
|
+
mDNSPlatformUnlock(&mDNSStorage);
|
|
282
300
|
}
|
|
283
301
|
#endif
|
|
284
302
|
|
|
@@ -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
|
|
@@ -701,10 +701,10 @@ DNSServiceErrorType DNSServiceQueryRecord
|
|
|
701
701
|
x->callback = callback;
|
|
702
702
|
x->context = context;
|
|
703
703
|
|
|
704
|
-
x->q.ThisQInterval = -1; // So that
|
|
704
|
+
x->q.ThisQInterval = -1; // So that DNSServiceQueryRecordDispose() knows whether to cancel this question
|
|
705
705
|
x->q.InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
|
|
706
706
|
x->q.Target = zeroAddr;
|
|
707
|
-
MakeDomainNameFromDNSNameString(&x->q.qname, fullname);
|
|
707
|
+
if (!MakeDomainNameFromDNSNameString(&x->q.qname, fullname)) { mDNSPlatformMemFree(x); err = mStatus_BadParamErr; errormsg = "MakeDomainNameFromDNSNameString"; goto fail; }
|
|
708
708
|
x->q.qtype = rrtype;
|
|
709
709
|
x->q.qclass = rrclass;
|
|
710
710
|
x->q.LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
|
|
@@ -721,7 +721,7 @@ DNSServiceErrorType DNSServiceQueryRecord
|
|
|
721
721
|
x->q.QuestionContext = x;
|
|
722
722
|
|
|
723
723
|
err = mDNS_StartQuery(&mDNSStorage, &x->q);
|
|
724
|
-
if (err) {
|
|
724
|
+
if (err) { DNSServiceQueryRecordDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
|
|
725
725
|
|
|
726
726
|
// Succeeded: Wrap up and return
|
|
727
727
|
*sdRef = (DNSServiceRef)x;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-zeroconf",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.3",
|
|
4
4
|
"description": "A Zeroconf discovery utility for react-native",
|
|
5
5
|
"main": "dist",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"!android/src/main/jni/mdnsresponder/mDNSShared/mDNSResponder.8",
|
|
58
58
|
"!android/build",
|
|
59
59
|
"!android/.gradle",
|
|
60
|
+
"!android/src/androidTest",
|
|
60
61
|
"windows",
|
|
61
62
|
"!windows/**/*.user",
|
|
62
63
|
"!windows/**/obj",
|