react-native-zeroconf 0.17.3 → 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 -17
- 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/mDNSShared/dnssd_clientshim.c +31 -6
- 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 +64 -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 -681
- package/android/src/main/java/com/github/druk/dnssd/DNSSDEmbedded.java +0 -198
- 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 -1221
- 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
|
@@ -1,654 +0,0 @@
|
|
|
1
|
-
package com.balthazargronon.RCTZeroconf.dnssd;
|
|
2
|
-
|
|
3
|
-
import android.annotation.SuppressLint;
|
|
4
|
-
import android.content.Context;
|
|
5
|
-
import android.net.wifi.WifiManager;
|
|
6
|
-
import android.util.Log;
|
|
7
|
-
|
|
8
|
-
import com.balthazargronon.RCTZeroconf.Zeroconf;
|
|
9
|
-
import com.balthazargronon.RCTZeroconf.ZeroconfModule;
|
|
10
|
-
import com.balthazargronon.RCTZeroconf.ZeroconfOptions;
|
|
11
|
-
import com.facebook.react.bridge.Promise;
|
|
12
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
13
|
-
import com.facebook.react.bridge.ReadableArray;
|
|
14
|
-
import com.facebook.react.bridge.WritableArray;
|
|
15
|
-
import com.facebook.react.bridge.WritableMap;
|
|
16
|
-
import com.facebook.react.bridge.WritableNativeArray;
|
|
17
|
-
import com.facebook.react.bridge.WritableNativeMap;
|
|
18
|
-
import com.github.druk.dnssd.BrowseListener;
|
|
19
|
-
import com.github.druk.dnssd.DNSSD;
|
|
20
|
-
import com.github.druk.dnssd.DNSSDEmbedded;
|
|
21
|
-
import com.github.druk.dnssd.DNSSDException;
|
|
22
|
-
import com.github.druk.dnssd.DNSSDRegistration;
|
|
23
|
-
import com.github.druk.dnssd.DNSSDService;
|
|
24
|
-
import com.github.druk.dnssd.NSClass;
|
|
25
|
-
import com.github.druk.dnssd.NSType;
|
|
26
|
-
import com.github.druk.dnssd.QueryListener;
|
|
27
|
-
import com.github.druk.dnssd.RegisterListener;
|
|
28
|
-
import com.github.druk.dnssd.ResolveListener;
|
|
29
|
-
import com.github.druk.dnssd.TXTRecord;
|
|
30
|
-
|
|
31
|
-
import java.net.InetAddress;
|
|
32
|
-
import java.net.UnknownHostException;
|
|
33
|
-
import java.util.ArrayList;
|
|
34
|
-
import java.util.HashMap;
|
|
35
|
-
import java.util.LinkedHashMap;
|
|
36
|
-
import java.util.LinkedHashSet;
|
|
37
|
-
import java.util.List;
|
|
38
|
-
import java.util.Map;
|
|
39
|
-
import java.util.Set;
|
|
40
|
-
import java.util.concurrent.ExecutorService;
|
|
41
|
-
import java.util.concurrent.Executors;
|
|
42
|
-
|
|
43
|
-
import javax.annotation.Nullable;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Embedded mDNSResponder (dns_sd), the same browse, resolve and address queries as the iOS implementation.
|
|
47
|
-
* DNSSD calls can block while the embedded daemon starts, so they and all the state below run on one
|
|
48
|
-
* background thread. DNSSD delivers callbacks on the main thread, they are handed back to that thread.
|
|
49
|
-
*/
|
|
50
|
-
public class DnssdImpl implements Zeroconf {
|
|
51
|
-
private static final String TAG = "DnssdImpl";
|
|
52
|
-
|
|
53
|
-
private final ZeroconfModule zeroconfModule;
|
|
54
|
-
private final ReactApplicationContext reactApplicationContext;
|
|
55
|
-
private final DNSSD dnssd;
|
|
56
|
-
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
57
|
-
private final android.os.Handler mainHandler = new android.os.Handler(android.os.Looper.getMainLooper());
|
|
58
|
-
private WifiManager.MulticastLock multicastLock;
|
|
59
|
-
|
|
60
|
-
// Running scans, keyed by the id of the JS instance that started them
|
|
61
|
-
private final Map<String, Scan> scans = new HashMap<>();
|
|
62
|
-
// Published services, keyed by the requested name
|
|
63
|
-
private final Map<String, Publication> publications = new LinkedHashMap<>();
|
|
64
|
-
|
|
65
|
-
private static class Scan {
|
|
66
|
-
final String scanId;
|
|
67
|
-
final boolean typesOnly;
|
|
68
|
-
int ifIndex = DNSSD.ALL_INTERFACES;
|
|
69
|
-
long resolveTimeoutMs = 5000;
|
|
70
|
-
DNSSDService browse;
|
|
71
|
-
// A service is reported once per network interface, count them so found/remove are emitted once
|
|
72
|
-
final Map<String, Integer> foundInterfaces = new HashMap<>();
|
|
73
|
-
final Map<String, Resolve> resolves = new HashMap<>();
|
|
74
|
-
|
|
75
|
-
Scan(String scanId, boolean typesOnly) {
|
|
76
|
-
this.scanId = scanId;
|
|
77
|
-
this.typesOnly = typesOnly;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private static class Resolve {
|
|
82
|
-
final String name;
|
|
83
|
-
// resolveService(): settled instead of emitting events
|
|
84
|
-
@Nullable Promise promise;
|
|
85
|
-
final List<DNSSDService> operations = new ArrayList<>();
|
|
86
|
-
String fullName;
|
|
87
|
-
String host;
|
|
88
|
-
int port;
|
|
89
|
-
Map<String, String> txt = new LinkedHashMap<>();
|
|
90
|
-
final Set<String> addresses = new LinkedHashSet<>();
|
|
91
|
-
// Scans: emitted once an address is known, retried once after a timeout
|
|
92
|
-
boolean emitted;
|
|
93
|
-
boolean retried;
|
|
94
|
-
|
|
95
|
-
Resolve(String name) {
|
|
96
|
-
this.name = name;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
void stop() {
|
|
100
|
-
for (DNSSDService operation : operations) {
|
|
101
|
-
operation.stop();
|
|
102
|
-
}
|
|
103
|
-
operations.clear();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private static class Publication {
|
|
108
|
-
final String requestedName;
|
|
109
|
-
final int port;
|
|
110
|
-
final Map<String, String> txt;
|
|
111
|
-
DNSSDRegistration registration;
|
|
112
|
-
@Nullable Promise promise;
|
|
113
|
-
String name;
|
|
114
|
-
String regType;
|
|
115
|
-
String domain;
|
|
116
|
-
boolean registered;
|
|
117
|
-
|
|
118
|
-
Publication(String requestedName, int port, Map<String, String> txt, @Nullable Promise promise) {
|
|
119
|
-
this.requestedName = requestedName;
|
|
120
|
-
this.name = requestedName;
|
|
121
|
-
this.port = port;
|
|
122
|
-
this.txt = txt;
|
|
123
|
-
this.promise = promise;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
public DnssdImpl(ZeroconfModule zeroconfModule, ReactApplicationContext reactApplicationContext) {
|
|
128
|
-
this.zeroconfModule = zeroconfModule;
|
|
129
|
-
this.reactApplicationContext = reactApplicationContext;
|
|
130
|
-
// The embedded mDNSResponder works on every Android version, the system daemon is missing on most devices
|
|
131
|
-
this.dnssd = new DNSSDEmbedded(reactApplicationContext);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Scan
|
|
135
|
-
|
|
136
|
-
@Override
|
|
137
|
-
public void scan(final String scanId, final String type, final String protocol, final String domain, final ZeroconfOptions options) {
|
|
138
|
-
executor.execute(() -> startScan(scanId, type, protocol, domain, options));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
private void startScan(String scanId, String type, String protocol, String domain, ZeroconfOptions options) {
|
|
142
|
-
stopScan(scanId);
|
|
143
|
-
|
|
144
|
-
final Scan scan = new Scan(scanId, ZeroconfModule.isServiceTypesScan(type, protocol));
|
|
145
|
-
final int ifIndex = interfaceIndex(options.networkInterface);
|
|
146
|
-
if (ifIndex < 0) {
|
|
147
|
-
zeroconfModule.sendError(ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_UNKNOWN_INTERFACE, "Unknown network interface " + options.networkInterface, null, scanId);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
scan.ifIndex = ifIndex;
|
|
151
|
-
scan.resolveTimeoutMs = (long) (options.resolveTimeoutSeconds * 1000);
|
|
152
|
-
// "_ipp._tcp,_printer" browses the _printer subtype
|
|
153
|
-
String regType = String.format("_%s._%s", type, protocol);
|
|
154
|
-
if (options.subtype != null) {
|
|
155
|
-
regType = ZeroconfOptions.withSubtypes(regType, java.util.Collections.singletonList(options.subtype));
|
|
156
|
-
}
|
|
157
|
-
Log.d(TAG, "Starting DNSSD scan " + scanId + " for " + regType);
|
|
158
|
-
acquireMulticastLock();
|
|
159
|
-
try {
|
|
160
|
-
scan.browse = dnssd.browse(0, ifIndex, regType, domainOrLocal(domain), new BrowseListener() {
|
|
161
|
-
@Override
|
|
162
|
-
public void serviceFound(DNSSDService browser, int flags, int ifIndex, String serviceName, String regType, String domain) {
|
|
163
|
-
executor.execute(() -> onServiceFound(scan, ifIndex, serviceName, regType, domain));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
@Override
|
|
167
|
-
public void serviceLost(DNSSDService browser, int flags, int ifIndex, String serviceName, String regType, String domain) {
|
|
168
|
-
executor.execute(() -> onServiceLost(scan, serviceName, regType));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
@Override
|
|
172
|
-
public void operationFailed(DNSSDService service, int errorCode) {
|
|
173
|
-
executor.execute(() -> {
|
|
174
|
-
if (scans.get(scan.scanId) != scan) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
sendError(errorCode, "Browsing services failed: ", null, scan.scanId);
|
|
178
|
-
stopScan(scan.scanId);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
} catch (DNSSDException e) {
|
|
183
|
-
releaseMulticastLock();
|
|
184
|
-
sendError(e.getErrorCode(), "Browsing services failed: ", null, scanId);
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
scans.put(scanId, scan);
|
|
188
|
-
sendScanEvent(ZeroconfModule.EVENT_START, new WritableNativeMap(), scanId);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private void onServiceFound(Scan scan, int ifIndex, String serviceName, String regType, String domain) {
|
|
192
|
-
if (scans.get(scan.scanId) != scan) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
String name = scan.typesOnly ? ZeroconfModule.serviceTypeFromResult(serviceName, regType) : serviceName;
|
|
196
|
-
Integer count = scan.foundInterfaces.get(name);
|
|
197
|
-
scan.foundInterfaces.put(name, count == null ? 1 : count + 1);
|
|
198
|
-
if (count != null) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
sendScanEvent(ZeroconfModule.EVENT_FOUND, nameToMap(name), scan.scanId);
|
|
202
|
-
// Service types are not resolved
|
|
203
|
-
if (!scan.typesOnly) {
|
|
204
|
-
startResolve(scan, ifIndex, serviceName, regType, domain, null);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private void onServiceLost(Scan scan, String serviceName, String regType) {
|
|
209
|
-
if (scans.get(scan.scanId) != scan) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
String name = scan.typesOnly ? ZeroconfModule.serviceTypeFromResult(serviceName, regType) : serviceName;
|
|
213
|
-
Integer count = scan.foundInterfaces.get(name);
|
|
214
|
-
if (count == null) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
if (count > 1) {
|
|
218
|
-
scan.foundInterfaces.put(name, count - 1);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
scan.foundInterfaces.remove(name);
|
|
222
|
-
Resolve resolve = scan.resolves.remove(name);
|
|
223
|
-
if (resolve != null) {
|
|
224
|
-
resolve.stop();
|
|
225
|
-
}
|
|
226
|
-
sendScanEvent(ZeroconfModule.EVENT_REMOVE, nameToMap(name), scan.scanId);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
@Override
|
|
230
|
-
public void stop(final String scanId) {
|
|
231
|
-
executor.execute(() -> stopScan(scanId));
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
@Override
|
|
235
|
-
public void stopAll() {
|
|
236
|
-
executor.execute(() -> {
|
|
237
|
-
for (String scanId : new ArrayList<>(scans.keySet())) {
|
|
238
|
-
stopScan(scanId);
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private void stopScan(String scanId) {
|
|
244
|
-
Scan scan = scans.remove(scanId);
|
|
245
|
-
if (scan == null) {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
if (scan.browse != null) {
|
|
249
|
-
scan.browse.stop();
|
|
250
|
-
}
|
|
251
|
-
for (Resolve resolve : scan.resolves.values()) {
|
|
252
|
-
resolve.stop();
|
|
253
|
-
}
|
|
254
|
-
scan.resolves.clear();
|
|
255
|
-
scan.foundInterfaces.clear();
|
|
256
|
-
releaseMulticastLock();
|
|
257
|
-
sendScanEvent(ZeroconfModule.EVENT_STOP, new WritableNativeMap(), scanId);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Resolve: host, port and TXT record, then the host's IPv4 and IPv6 addresses
|
|
261
|
-
|
|
262
|
-
private void startResolve(@Nullable final Scan scan, final int ifIndex, final String serviceName, final String regType, final String domain, @Nullable Resolve existing) {
|
|
263
|
-
final Resolve resolve = existing != null ? existing : new Resolve(serviceName);
|
|
264
|
-
if (scan != null) {
|
|
265
|
-
scan.resolves.put(serviceName, resolve);
|
|
266
|
-
// DNSSD gives up silently after its own timeout, report it before
|
|
267
|
-
mainHandler.postDelayed(() -> executor.execute(() -> {
|
|
268
|
-
if (!isCurrent(scan, resolve) || resolve.emitted) {
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
resolve.stop();
|
|
272
|
-
// Slow devices can time out, retry once before reporting the error
|
|
273
|
-
if (!resolve.retried) {
|
|
274
|
-
resolve.retried = true;
|
|
275
|
-
startResolve(scan, ifIndex, serviceName, regType, domain, resolve);
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
scan.resolves.remove(serviceName);
|
|
279
|
-
zeroconfModule.sendError(ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_TIMEOUT, "Resolving service " + serviceName + " failed: timed out", serviceName, scan.scanId);
|
|
280
|
-
}), scan.resolveTimeoutMs);
|
|
281
|
-
}
|
|
282
|
-
try {
|
|
283
|
-
resolve.operations.add(dnssd.resolve(0, ifIndex, serviceName, regType, domain, new ResolveListener() {
|
|
284
|
-
@Override
|
|
285
|
-
public void serviceResolved(DNSSDService resolver, int flags, int ifIndex, String fullName, String hostName, int port, Map<String, String> txtRecord) {
|
|
286
|
-
executor.execute(() -> {
|
|
287
|
-
if (!isCurrent(scan, resolve)) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
resolve.fullName = fullName;
|
|
291
|
-
resolve.host = hostName;
|
|
292
|
-
resolve.port = port;
|
|
293
|
-
resolve.txt = txtRecord;
|
|
294
|
-
queryAddresses(scan, resolve, ifIndex);
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
@Override
|
|
299
|
-
public void operationFailed(DNSSDService service, int errorCode) {
|
|
300
|
-
executor.execute(() -> onResolveFailed(scan, resolve, errorCode));
|
|
301
|
-
}
|
|
302
|
-
}));
|
|
303
|
-
} catch (DNSSDException e) {
|
|
304
|
-
onResolveFailed(scan, resolve, e.getErrorCode());
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
private void queryAddresses(@Nullable final Scan scan, final Resolve resolve, int ifIndex) {
|
|
309
|
-
QueryListener listener = new QueryListener() {
|
|
310
|
-
@Override
|
|
311
|
-
public void queryAnswered(DNSSDService query, int flags, int ifIndex, String fullName, int rrtype, int rrclass, byte[] rdata, int ttl) {
|
|
312
|
-
executor.execute(() -> {
|
|
313
|
-
if (!isCurrent(scan, resolve)) {
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
try {
|
|
317
|
-
resolve.addresses.add(InetAddress.getByAddress(rdata).getHostAddress());
|
|
318
|
-
} catch (UnknownHostException e) {
|
|
319
|
-
Log.w(TAG, "Invalid address record for " + resolve.host, e);
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
if (scan == null) {
|
|
323
|
-
// resolveService() settles with the first address
|
|
324
|
-
endSingleResolve(resolve);
|
|
325
|
-
resolve.promise.resolve(resolveToMap(resolve));
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
// Emitted for each address, the first one is usable right away
|
|
329
|
-
resolve.emitted = true;
|
|
330
|
-
sendScanEvent(ZeroconfModule.EVENT_RESOLVE, resolveToMap(resolve), scan.scanId);
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
@Override
|
|
335
|
-
public void operationFailed(DNSSDService service, int errorCode) {
|
|
336
|
-
executor.execute(() -> onResolveFailed(scan, resolve, errorCode));
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
try {
|
|
340
|
-
// Each query stops after its first answer, or silently after a timeout (no AAAA record for example)
|
|
341
|
-
resolve.operations.add(dnssd.queryRecord(0, ifIndex, resolve.host, NSType.A, NSClass.IN, true, listener));
|
|
342
|
-
resolve.operations.add(dnssd.queryRecord(0, ifIndex, resolve.host, NSType.AAAA, NSClass.IN, true, listener));
|
|
343
|
-
} catch (DNSSDException e) {
|
|
344
|
-
onResolveFailed(scan, resolve, e.getErrorCode());
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
private boolean isCurrent(@Nullable Scan scan, Resolve resolve) {
|
|
349
|
-
if (scan == null) {
|
|
350
|
-
return singleResolves.contains(resolve);
|
|
351
|
-
}
|
|
352
|
-
return scans.get(scan.scanId) == scan && scan.resolves.get(resolve.name) == resolve;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
private void onResolveFailed(@Nullable Scan scan, Resolve resolve, int errorCode) {
|
|
356
|
-
if (!isCurrent(scan, resolve)) {
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
if (scan == null) {
|
|
360
|
-
endSingleResolve(resolve);
|
|
361
|
-
String message = "Resolving service " + resolve.name + " failed: " + ZeroconfModule.describeDnssdError(errorCode);
|
|
362
|
-
ZeroconfModule.reject(resolve.promise, ZeroconfModule.ERROR_DOMAIN_DNSSD, errorCode, message, resolve.name);
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
scan.resolves.remove(resolve.name);
|
|
366
|
-
resolve.stop();
|
|
367
|
-
sendError(errorCode, "Resolving service " + resolve.name + " failed: ", resolve.name, scan.scanId);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// resolveService(): one service by name, without scanning
|
|
371
|
-
|
|
372
|
-
private final Set<Resolve> singleResolves = new LinkedHashSet<>();
|
|
373
|
-
|
|
374
|
-
@Override
|
|
375
|
-
public void resolveService(final String name, final String type, final String protocol, final String domain, final ZeroconfOptions options, final Promise promise) {
|
|
376
|
-
executor.execute(() -> {
|
|
377
|
-
int ifIndex = interfaceIndex(options.networkInterface);
|
|
378
|
-
if (ifIndex < 0) {
|
|
379
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_UNKNOWN_INTERFACE, "Unknown network interface " + options.networkInterface, null);
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
final Resolve resolve = new Resolve(name);
|
|
383
|
-
resolve.promise = promise;
|
|
384
|
-
singleResolves.add(resolve);
|
|
385
|
-
acquireMulticastLock();
|
|
386
|
-
startResolve(null, ifIndex, name, String.format("_%s._%s", type, protocol), domainOrLocal(domain), resolve);
|
|
387
|
-
// DNSSD gives up silently after its own timeout, settle the promise before
|
|
388
|
-
mainHandler.postDelayed(() -> executor.execute(() -> {
|
|
389
|
-
if (!singleResolves.contains(resolve)) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
endSingleResolve(resolve);
|
|
393
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_TIMEOUT, "Resolving service " + name + " failed: timed out", name);
|
|
394
|
-
}), (long) (options.timeoutSeconds * 1000));
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
private void endSingleResolve(Resolve resolve) {
|
|
399
|
-
if (singleResolves.remove(resolve)) {
|
|
400
|
-
resolve.stop();
|
|
401
|
-
releaseMulticastLock();
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// Publish
|
|
406
|
-
|
|
407
|
-
@Override
|
|
408
|
-
public void registerService(final String type, final String protocol, final String domain, final String name, final int port, final ReadableArray txt, final ZeroconfOptions options, final Promise promise) {
|
|
409
|
-
// Read the TXT record on the calling thread, the array belongs to the bridge call
|
|
410
|
-
final Map<String, String> txtMap = getTxtRecordMap(txt);
|
|
411
|
-
executor.execute(() -> startPublication(type, protocol, domain, name, port, txtMap, options, promise));
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
private void startPublication(String type, String protocol, String domain, String name, int port, Map<String, String> txt, ZeroconfOptions options, Promise promise) {
|
|
415
|
-
int ifIndex = interfaceIndex(options.networkInterface);
|
|
416
|
-
if (ifIndex < 0) {
|
|
417
|
-
String message = "Unknown network interface " + options.networkInterface;
|
|
418
|
-
zeroconfModule.sendError(ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_UNKNOWN_INTERFACE, message, name, null);
|
|
419
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_UNKNOWN_INTERFACE, message, name);
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
Publication previous = publications.remove(name);
|
|
423
|
-
if (previous != null) {
|
|
424
|
-
previous.registration.stop();
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
final Publication publication = new Publication(name, port, txt, promise);
|
|
428
|
-
// "_ipp._tcp,_printer,_color" registers the subtypes too
|
|
429
|
-
String regType = ZeroconfOptions.withSubtypes(String.format("_%s._%s", type, protocol), options.subtypes);
|
|
430
|
-
try {
|
|
431
|
-
publication.registration = dnssd.register(0, ifIndex, name, regType, null, null, port, toTXTRecord(txt), new RegisterListener() {
|
|
432
|
-
@Override
|
|
433
|
-
public void serviceRegistered(DNSSDRegistration registration, int flags, String serviceName, String regType, String domain) {
|
|
434
|
-
executor.execute(() -> onRegistered(publication, serviceName, regType, domain));
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
@Override
|
|
438
|
-
public void operationFailed(DNSSDService service, int errorCode) {
|
|
439
|
-
executor.execute(() -> onRegistrationFailed(publication, errorCode));
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
} catch (DNSSDException e) {
|
|
443
|
-
String prefix = "Registering service " + name + " failed: ";
|
|
444
|
-
sendError(e.getErrorCode(), prefix, name, null);
|
|
445
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_DNSSD, e.getErrorCode(), prefix + ZeroconfModule.describeDnssdError(e.getErrorCode()), name);
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
publications.put(name, publication);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
private void onRegistered(Publication publication, String serviceName, String regType, String domain) {
|
|
452
|
-
if (publications.get(publication.requestedName) != publication) {
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
publication.name = serviceName;
|
|
456
|
-
publication.regType = regType;
|
|
457
|
-
publication.domain = domain;
|
|
458
|
-
if (publication.registered) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
publication.registered = true;
|
|
462
|
-
Log.i(TAG, "Registered service " + serviceName);
|
|
463
|
-
zeroconfModule.sendEvent(reactApplicationContext, ZeroconfModule.EVENT_PUBLISHED, publicationToMap(publication));
|
|
464
|
-
if (publication.promise != null) {
|
|
465
|
-
publication.promise.resolve(publicationToMap(publication));
|
|
466
|
-
publication.promise = null;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
private void onRegistrationFailed(Publication publication, int errorCode) {
|
|
471
|
-
if (publications.get(publication.requestedName) != publication) {
|
|
472
|
-
return;
|
|
473
|
-
}
|
|
474
|
-
publications.remove(publication.requestedName);
|
|
475
|
-
publication.registration.stop();
|
|
476
|
-
String prefix = "Registering service " + publication.requestedName + " failed: ";
|
|
477
|
-
sendError(errorCode, prefix, publication.requestedName, null);
|
|
478
|
-
ZeroconfModule.reject(publication.promise, ZeroconfModule.ERROR_DOMAIN_DNSSD, errorCode, prefix + ZeroconfModule.describeDnssdError(errorCode), publication.requestedName);
|
|
479
|
-
publication.promise = null;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
@Override
|
|
483
|
-
public void updateService(final String serviceName, final ReadableArray txt, final Promise promise) {
|
|
484
|
-
final Map<String, String> txtMap = getTxtRecordMap(txt);
|
|
485
|
-
executor.execute(() -> {
|
|
486
|
-
Publication publication = findPublication(serviceName);
|
|
487
|
-
if (publication == null || !publication.registered) {
|
|
488
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_NOT_PUBLISHED, "Service " + serviceName + " is not published", serviceName);
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
try {
|
|
492
|
-
publication.registration.getTXTRecord().update(0, toTXTRecord(txtMap).getRawBytes(), 0);
|
|
493
|
-
} catch (DNSSDException e) {
|
|
494
|
-
String message = "Updating service " + serviceName + " failed: " + ZeroconfModule.describeDnssdError(e.getErrorCode());
|
|
495
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_DNSSD, e.getErrorCode(), message, serviceName);
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
publication.txt.clear();
|
|
499
|
-
publication.txt.putAll(txtMap);
|
|
500
|
-
promise.resolve(publicationToMap(publication));
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
@Nullable
|
|
505
|
-
private Publication findPublication(String serviceName) {
|
|
506
|
-
// By the requested name, or the name it was published under when it was renamed
|
|
507
|
-
Publication publication = publications.get(serviceName);
|
|
508
|
-
if (publication == null) {
|
|
509
|
-
for (Publication candidate : publications.values()) {
|
|
510
|
-
if (candidate.name.equals(serviceName)) {
|
|
511
|
-
return candidate;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return publication;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
@Override
|
|
519
|
-
public void unregisterService(final String serviceName, @Nullable final Promise promise) {
|
|
520
|
-
executor.execute(() -> stopPublication(serviceName, promise));
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
@Override
|
|
524
|
-
public void unregisterAllServices() {
|
|
525
|
-
executor.execute(() -> {
|
|
526
|
-
for (String name : new ArrayList<>(publications.keySet())) {
|
|
527
|
-
stopPublication(name, null);
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
private void stopPublication(String serviceName, @Nullable Promise promise) {
|
|
533
|
-
Publication publication = findPublication(serviceName);
|
|
534
|
-
if (publication == null) {
|
|
535
|
-
ZeroconfModule.reject(promise, ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_NOT_PUBLISHED, "Service " + serviceName + " is not published", serviceName);
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
538
|
-
publications.remove(publication.requestedName);
|
|
539
|
-
// Stopping the registration unregisters synchronously
|
|
540
|
-
publication.registration.stop();
|
|
541
|
-
if (publication.promise != null) {
|
|
542
|
-
ZeroconfModule.reject(publication.promise, ZeroconfModule.ERROR_DOMAIN_LIBRARY, ZeroconfModule.ERROR_CODE_NOT_PUBLISHED, "Service " + serviceName + " was unpublished before it was published", serviceName);
|
|
543
|
-
publication.promise = null;
|
|
544
|
-
}
|
|
545
|
-
WritableMap service = publicationToMap(publication);
|
|
546
|
-
if (publication.registered) {
|
|
547
|
-
zeroconfModule.sendEvent(reactApplicationContext, ZeroconfModule.EVENT_UNREGISTERED, publicationToMap(publication));
|
|
548
|
-
}
|
|
549
|
-
if (promise != null) {
|
|
550
|
-
promise.resolve(service);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// Helpers
|
|
555
|
-
|
|
556
|
-
// The index of a network interface by name, DNSSD.ALL_INTERFACES without one, -1 when it doesn't exist
|
|
557
|
-
private static int interfaceIndex(@Nullable String networkInterface) {
|
|
558
|
-
if (networkInterface == null) {
|
|
559
|
-
return DNSSD.ALL_INTERFACES;
|
|
560
|
-
}
|
|
561
|
-
int index = DNSSD.getIfIndexForName(networkInterface);
|
|
562
|
-
return index > 0 ? index : -1;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
private static TXTRecord toTXTRecord(Map<String, String> txt) {
|
|
566
|
-
TXTRecord txtRecord = new TXTRecord();
|
|
567
|
-
for (Map.Entry<String, String> entry : txt.entrySet()) {
|
|
568
|
-
txtRecord.set(entry.getKey(), entry.getValue());
|
|
569
|
-
}
|
|
570
|
-
return txtRecord;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
private static String domainOrLocal(@Nullable String domain) {
|
|
574
|
-
return domain == null || domain.isEmpty() ? "local." : domain;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
private void sendScanEvent(String eventName, WritableMap body, String scanId) {
|
|
578
|
-
body.putString(ZeroconfModule.KEY_SCAN_ID, scanId);
|
|
579
|
-
zeroconfModule.sendEvent(reactApplicationContext, eventName, body);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
private void sendError(int errorCode, String prefix, @Nullable String serviceName, @Nullable String scanId) {
|
|
583
|
-
zeroconfModule.sendError(ZeroconfModule.ERROR_DOMAIN_DNSSD, errorCode, prefix + ZeroconfModule.describeDnssdError(errorCode), serviceName, scanId);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
private void acquireMulticastLock() {
|
|
587
|
-
if (multicastLock == null) {
|
|
588
|
-
@SuppressLint("WifiManagerLeak") WifiManager wifi = (WifiManager) reactApplicationContext.getSystemService(Context.WIFI_SERVICE);
|
|
589
|
-
multicastLock = wifi.createMulticastLock("multicastLock");
|
|
590
|
-
multicastLock.setReferenceCounted(true);
|
|
591
|
-
}
|
|
592
|
-
multicastLock.acquire();
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
private void releaseMulticastLock() {
|
|
596
|
-
if (multicastLock != null && multicastLock.isHeld()) {
|
|
597
|
-
multicastLock.release();
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
private static WritableMap nameToMap(String name) {
|
|
602
|
-
WritableMap service = new WritableNativeMap();
|
|
603
|
-
service.putString(ZeroconfModule.KEY_SERVICE_NAME, name);
|
|
604
|
-
return service;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
private static WritableMap resolveToMap(Resolve resolve) {
|
|
608
|
-
WritableMap service = new WritableNativeMap();
|
|
609
|
-
service.putString(ZeroconfModule.KEY_SERVICE_NAME, resolve.name);
|
|
610
|
-
service.putString(ZeroconfModule.KEY_SERVICE_FULL_NAME, resolve.fullName);
|
|
611
|
-
service.putString(ZeroconfModule.KEY_SERVICE_HOST, resolve.host);
|
|
612
|
-
service.putInt(ZeroconfModule.KEY_SERVICE_PORT, resolve.port);
|
|
613
|
-
WritableArray addresses = new WritableNativeArray();
|
|
614
|
-
for (String address : resolve.addresses) {
|
|
615
|
-
addresses.pushString(address);
|
|
616
|
-
}
|
|
617
|
-
service.putArray(ZeroconfModule.KEY_SERVICE_ADDRESSES, addresses);
|
|
618
|
-
service.putMap(ZeroconfModule.KEY_SERVICE_TXT, txtToMap(resolve.txt));
|
|
619
|
-
return service;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
private static WritableMap publicationToMap(Publication publication) {
|
|
623
|
-
WritableMap service = new WritableNativeMap();
|
|
624
|
-
service.putString(ZeroconfModule.KEY_SERVICE_NAME, publication.name);
|
|
625
|
-
service.putString(ZeroconfModule.KEY_SERVICE_FULL_NAME, publication.regType != null
|
|
626
|
-
? publication.name + "." + publication.regType + domainOrLocal(publication.domain)
|
|
627
|
-
: publication.name);
|
|
628
|
-
service.putString(ZeroconfModule.KEY_SERVICE_HOST, publication.name);
|
|
629
|
-
service.putInt(ZeroconfModule.KEY_SERVICE_PORT, publication.port);
|
|
630
|
-
service.putArray(ZeroconfModule.KEY_SERVICE_ADDRESSES, new WritableNativeArray());
|
|
631
|
-
service.putMap(ZeroconfModule.KEY_SERVICE_TXT, txtToMap(publication.txt));
|
|
632
|
-
return service;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
private static WritableMap txtToMap(@Nullable Map<String, String> txt) {
|
|
636
|
-
WritableMap map = new WritableNativeMap();
|
|
637
|
-
if (txt != null) {
|
|
638
|
-
for (Map.Entry<String, String> entry : txt.entrySet()) {
|
|
639
|
-
map.putString(entry.getKey(), entry.getValue() != null ? entry.getValue() : "");
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
return map;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
private static Map<String, String> getTxtRecordMap(ReadableArray txt) {
|
|
646
|
-
// LinkedHashMap keeps the TXT record order
|
|
647
|
-
Map<String, String> txtMap = new LinkedHashMap<>();
|
|
648
|
-
for (int i = 0; i < txt.size(); i++) {
|
|
649
|
-
ReadableArray pair = txt.getArray(i);
|
|
650
|
-
txtMap.put(pair.getString(0), pair.getString(1));
|
|
651
|
-
}
|
|
652
|
-
return txtMap;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (C) 2016 Andriy Druk
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
package com.github.druk.dnssd;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/** A base class for DNSSD listeners. */
|
|
21
|
-
|
|
22
|
-
public interface BaseListener {
|
|
23
|
-
/** Called to report DNSSD operation failures.<P>
|
|
24
|
-
|
|
25
|
-
@param service
|
|
26
|
-
The service that encountered the failure.
|
|
27
|
-
<P>
|
|
28
|
-
@param errorCode
|
|
29
|
-
Indicates the failure that occurred. See {@link DNSSDException} for error codes.
|
|
30
|
-
*/
|
|
31
|
-
void operationFailed(DNSSDService service, int errorCode);
|
|
32
|
-
}
|
|
33
|
-
|