1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16
17 Change History (most recent first):
18
19 $Log: JNISupport.c,v $
20 Revision 1.17 2006/08/14 23:25:08 cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
22
23 Revision 1.16 2006/07/14 02:35:47 cheshire
24 Added (commented out) syslog debugging messages
25
26 Revision 1.15 2006/06/27 19:34:43 cheshire
27 <rdar://problem/4430023> txtRecord parameter of DNSServiceResolveReply() should be unsigned char *
28
29 Revision 1.14 2006/06/20 23:03:35 rpantos
30 <rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
31
32 Revision 1.13 2005/10/26 01:52:24 cheshire
33 <rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
34
35 Revision 1.12 2005/07/13 19:20:32 cheshire
36 <rdar://problem/4175511> Race condition in Java API
37 Additional cleanup suggested by Roger -- NewContext() doesn't need ownerClass parameter any more
38
39 Revision 1.11 2005/07/11 01:55:21 cheshire
40 <rdar://problem/4175511> Race condition in Java API
41
42 Revision 1.10 2005/07/05 13:01:52 cheshire
43 <rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
44
45 Revision 1.9 2004/12/11 03:01:00 rpantos
46 <rdar://problem/3907498> Java DNSRecord API should be cleaned up
47
48 Revision 1.8 2004/11/30 23:51:05 cheshire
49 Remove double semicolons
50
51 Revision 1.7 2004/11/23 08:12:04 shersche
52 Implement if_nametoindex and if_indextoname for Win32 platforms
53
54 Revision 1.6 2004/11/23 03:41:14 cheshire
55 Change JNISupport.c to call if_indextoname & if_nametoindex directly.
56 (May require some additional glue code to work on Windows.)
57
58 Revision 1.5 2004/11/17 17:07:44 cheshire
59 Updated comment about AUTO_CALLBACKS
60
61 Revision 1.4 2004/11/12 03:23:09 rpantos
62 rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
63
64 Revision 1.3 2004/06/18 04:44:17 rpantos
65 Adapt to API unification on Windows
66
67 Revision 1.2 2004/05/28 23:34:42 ksekar
68 <rdar://problem/3672903>: Java project build errors
69
70 Revision 1.1 2004/04/30 16:29:35 rpantos
71 First checked in.
72
73
74 This file contains the platform support for DNSSD and related Java classes.
75 It is used to shim through to the underlying <dns_sd.h> API.
76 */
77
78 #pragma ident "%Z%%M% %I% %E% SMI"
79
80 // AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
81 // callbacks automatically (as in the early Windows prototypes).
82 // AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
83 // invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.).
84 // (Invoking callbacks automatically on a different thread sounds attractive, but while
85 // the client gains by not needing to add an event source to its main event loop, it loses
86 // by being forced to deal with concurrency and locking, which can be a bigger burden.)
87 #ifndef AUTO_CALLBACKS
88 #define AUTO_CALLBACKS 0
89 #endif
90
91 #if !AUTO_CALLBACKS
92 #ifdef _WIN32
93 #include <winsock2.h>
94 #else //_WIN32
95 #include <sys/types.h>
96 #include <sys/select.h>
97 #endif // _WIN32
98 #endif // AUTO_CALLBACKS
99
100 #include <dns_sd.h>
101
102 #include <stdio.h>
103 #include <stdlib.h>
104 #include <string.h>
105 #ifdef _WIN32
106 #include <winsock2.h>
107 #include <iphlpapi.h>
108 static char * if_indextoname( DWORD ifIndex, char * nameBuff);
109 static DWORD if_nametoindex( const char * nameStr );
110 #define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
111 #else // _WIN32
112 #include <sys/socket.h>
113 #include <net/if.h>
114 #endif // _WIN32
115 #include <jni.h>
116
117 #include "DNSSD.java.h"
118
119 //#include <syslog.h>
120
121 // convenience definition
122 #ifdef __GNUC__
123 #define _UNUSED __attribute__ ((unused))
124 #else
125 #define _UNUSED
126 #endif
127
128 enum {
129 kInterfaceVersion = 1 // Must match version in .jar file
130 };
131
132 typedef struct OpContext OpContext;
133
134 struct OpContext
135 {
136 DNSServiceRef ServiceRef;
137 JNIEnv *Env;
138 jobject JavaObj;
139 jobject ClientObj;
140 jmethodID Callback;
141 jmethodID Callback2;
142 };
143
144 // For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
145 #if AUTO_CALLBACKS
146 JavaVM *gJavaVM = NULL;
147 #endif
148
149
Java_com_apple_dnssd_AppleDNSSD_InitLibrary(JNIEnv * pEnv,jclass cls,jint callerVersion)150 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
151 jint callerVersion)
152 {
153 /* Ensure that caller & interface versions match. */
154 if ( callerVersion != kInterfaceVersion)
155 return kDNSServiceErr_Incompatible;
156
157 #if AUTO_CALLBACKS
158 {
159 jsize numVMs;
160
161 if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
162 return kDNSServiceErr_BadState;
163 }
164 #endif
165
166 // Set AppleDNSSD.hasAutoCallbacks
167 {
168 #if AUTO_CALLBACKS
169 jboolean hasAutoC = JNI_TRUE;
170 #else
171 jboolean hasAutoC = JNI_FALSE;
172 #endif
173 jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
174 (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
175 }
176
177 return kDNSServiceErr_NoError;
178 }
179
180
SafeGetUTFChars(JNIEnv * pEnv,jstring str)181 static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str)
182 // Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
183 {
184 return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
185 }
186
SafeReleaseUTFChars(JNIEnv * pEnv,jstring str,const char * buff)187 static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
188 // Wrapper for JNI GetStringUTFChars() that handles null str.
189 {
190 if ( str != NULL)
191 (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
192 }
193
194
195 #if AUTO_CALLBACKS
SetupCallbackState(JNIEnv ** ppEnv)196 static void SetupCallbackState( JNIEnv **ppEnv)
197 {
198 (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
199 }
200
TeardownCallbackState(void)201 static void TeardownCallbackState( void )
202 {
203 (*gJavaVM)->DetachCurrentThread( gJavaVM);
204 }
205
206 #else // AUTO_CALLBACKS
207
SetupCallbackState(JNIEnv ** ppEnv _UNUSED)208 static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
209 {
210 // No setup necessary if ProcessResults() has been called
211 }
212
TeardownCallbackState(void)213 static void TeardownCallbackState( void )
214 {
215 // No teardown necessary if ProcessResults() has been called
216 }
217 #endif // AUTO_CALLBACKS
218
219
NewContext(JNIEnv * pEnv,jobject owner,const char * callbackName,const char * callbackSig)220 static OpContext *NewContext( JNIEnv *pEnv, jobject owner,
221 const char *callbackName, const char *callbackSig)
222 // Create and initialize a new OpContext.
223 {
224 OpContext *pContext = (OpContext*) malloc( sizeof *pContext);
225
226 if ( pContext != NULL)
227 {
228 jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
229 "fListener", "Lcom/apple/dnssd/BaseListener;");
230
231 pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); // must convert local ref to global to cache;
232 pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField);
233 pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); // must convert local ref to global to cache
234 pContext->Callback = (*pEnv)->GetMethodID( pEnv,
235 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
236 callbackName, callbackSig);
237 pContext->Callback2 = NULL; // not always used
238 }
239
240 return pContext;
241 }
242
243
ReportError(JNIEnv * pEnv,jobject target,jobject service,DNSServiceErrorType err)244 static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
245 // Invoke operationFailed() method on target with err.
246 {
247 jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
248 jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
249 "(Lcom/apple/dnssd/DNSSDService;I)V");
250
251 (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
252 }
253
Java_com_apple_dnssd_AppleService_HaltOperation(JNIEnv * pEnv,jobject pThis)254 JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis)
255 /* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
256 {
257 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
258 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
259
260 if ( contextField != 0)
261 {
262 OpContext *pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
263 if ( pContext != NULL)
264 {
265 // MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate()
266 (*pEnv)->SetLongField( pEnv, pThis, contextField, 0);
267 if ( pContext->ServiceRef != NULL)
268 DNSServiceRefDeallocate( pContext->ServiceRef);
269
270 (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
271 (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
272 free( pContext);
273 }
274 }
275 }
276
277
Java_com_apple_dnssd_AppleService_BlockForData(JNIEnv * pEnv,jobject pThis)278 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis)
279 /* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
280 {
281 // BlockForData() not supported with AUTO_CALLBACKS
282 #if !AUTO_CALLBACKS
283 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
284 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
285
286 if ( contextField != 0)
287 {
288 OpContext *pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
289 if ( pContext != NULL)
290 {
291 fd_set readFDs;
292 int sd = DNSServiceRefSockFD( pContext->ServiceRef);
293 struct timeval timeout = { 1, 0 };
294 FD_ZERO( &readFDs);
295 FD_SET( sd, &readFDs);
296
297 // Q: Why do we poll here?
298 // A: Because there's no other thread-safe way to do it.
299 // Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not,
300 // and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>)
301 // The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while
302 // some other thread is monitoring that socket in select(), but the difficulty is that there's no general way
303 // to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously.
304 // If we try to do this without holding any lock, then right as we jump to the select() routine,
305 // some other thread could stop our operation (thereby closing the socket),
306 // and then that thread (or even some third, unrelated thread)
307 // could do some other DNS-SD operation (or some other operation that opens a new file descriptor)
308 // and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor
309 // that may coincidentally have the same numerical value, but is semantically unrelated
310 // to the true file descriptor we thought we were blocking on.
311 // We can't stop this race condition from happening, but at least if we wake up once a second we can detect
312 // when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd.
313
314 if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1);
315 }
316 }
317 #endif // !AUTO_CALLBACKS
318 return(0);
319 }
320
321
Java_com_apple_dnssd_AppleService_ProcessResults(JNIEnv * pEnv,jobject pThis)322 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
323 /* Call through to DNSServiceProcessResult() while data remains on socket. */
324 {
325 #if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
326
327 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
328 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
329 OpContext *pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
330 DNSServiceErrorType err = kDNSServiceErr_BadState;
331
332 if ( pContext != NULL)
333 {
334 int sd = DNSServiceRefSockFD( pContext->ServiceRef);
335 fd_set readFDs;
336 struct timeval zeroTimeout = { 0, 0 };
337
338 pContext->Env = pEnv;
339
340 FD_ZERO( &readFDs);
341 FD_SET( sd, &readFDs);
342
343 err = kDNSServiceErr_NoError;
344 if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
345 {
346 err = DNSServiceProcessResult(pContext->ServiceRef);
347 // Use caution here!
348 // We cannot touch any data structures associated with this operation!
349 // The DNSServiceProcessResult() routine should have invoked our callback,
350 // and our callback could have terminated the operation with op.stop();
351 // and that means HaltOperation() will have been called, which frees pContext.
352 // Basically, from here we just have to get out without touching any stale
353 // data structures that could blow up on us! Particularly, any attempt
354 // to loop here reading more results from the file descriptor is unsafe.
355 }
356 }
357 return err;
358 #endif // AUTO_CALLBACKS
359 }
360
361
ServiceBrowseReply(DNSServiceRef sdRef _UNUSED,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regtype,const char * replyDomain,void * context)362 static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
363 DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
364 const char *replyDomain, void *context)
365 {
366 OpContext *pContext = (OpContext*) context;
367
368 SetupCallbackState( &pContext->Env);
369
370 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
371 {
372 if ( errorCode == kDNSServiceErr_NoError)
373 {
374 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
375 ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
376 pContext->JavaObj, flags, interfaceIndex,
377 (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
378 (*pContext->Env)->NewStringUTF( pContext->Env, regtype),
379 (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
380 }
381 else
382 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
383 }
384
385 TeardownCallbackState();
386 }
387
Java_com_apple_dnssd_AppleBrowser_CreateBrowser(JNIEnv * pEnv,jobject pThis,jint flags,jint ifIndex,jstring regType,jstring domain)388 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
389 jint flags, jint ifIndex, jstring regType, jstring domain)
390 {
391 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
392 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
393 OpContext *pContext = NULL;
394 DNSServiceErrorType err = kDNSServiceErr_NoError;
395
396 if ( contextField != 0)
397 pContext = NewContext( pEnv, pThis, "serviceFound",
398 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
399 else
400 err = kDNSServiceErr_BadParam;
401
402 if ( pContext != NULL)
403 {
404 const char *regStr = SafeGetUTFChars( pEnv, regType);
405 const char *domainStr = SafeGetUTFChars( pEnv, domain);
406
407 pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
408 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
409 "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
410
411 err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
412 if ( err == kDNSServiceErr_NoError)
413 {
414 (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
415 }
416
417 SafeReleaseUTFChars( pEnv, regType, regStr);
418 SafeReleaseUTFChars( pEnv, domain, domainStr);
419 }
420 else
421 err = kDNSServiceErr_NoMemory;
422
423 return err;
424 }
425
426
ServiceResolveReply(DNSServiceRef sdRef _UNUSED,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * fullname,const char * hosttarget,uint16_t port,uint16_t txtLen,const unsigned char * txtRecord,void * context)427 static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
428 DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget,
429 uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context)
430 {
431 OpContext *pContext = (OpContext*) context;
432 jclass txtCls;
433 jmethodID txtCtor;
434 jbyteArray txtBytes;
435 jobject txtObj;
436 jbyte *pBytes;
437
438 SetupCallbackState( &pContext->Env);
439
440 txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
441 txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
442
443 if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
444 NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
445 {
446 if ( errorCode == kDNSServiceErr_NoError)
447 {
448 // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
449 // pattern into a number here.
450 port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
451
452 // Initialize txtBytes with contents of txtRecord
453 pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL);
454 memcpy( pBytes, txtRecord, txtLen);
455 (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT);
456
457 // Construct txtObj with txtBytes
458 txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
459 (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
460
461 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
462 pContext->JavaObj, flags, interfaceIndex,
463 (*pContext->Env)->NewStringUTF( pContext->Env, fullname),
464 (*pContext->Env)->NewStringUTF( pContext->Env, hosttarget),
465 port, txtObj);
466 }
467 else
468 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
469 }
470
471 TeardownCallbackState();
472 }
473
Java_com_apple_dnssd_AppleResolver_CreateResolver(JNIEnv * pEnv,jobject pThis,jint flags,jint ifIndex,jstring serviceName,jstring regType,jstring domain)474 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis,
475 jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain)
476 {
477 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
478 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
479 OpContext *pContext = NULL;
480 DNSServiceErrorType err = kDNSServiceErr_NoError;
481
482 if ( contextField != 0)
483 pContext = NewContext( pEnv, pThis, "serviceResolved",
484 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
485 else
486 err = kDNSServiceErr_BadParam;
487
488 if ( pContext != NULL)
489 {
490 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
491 const char *regStr = SafeGetUTFChars( pEnv, regType);
492 const char *domainStr = SafeGetUTFChars( pEnv, domain);
493
494 err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
495 servStr, regStr, domainStr, ServiceResolveReply, pContext);
496 if ( err == kDNSServiceErr_NoError)
497 {
498 (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
499 }
500
501 SafeReleaseUTFChars( pEnv, serviceName, servStr);
502 SafeReleaseUTFChars( pEnv, regType, regStr);
503 SafeReleaseUTFChars( pEnv, domain, domainStr);
504 }
505 else
506 err = kDNSServiceErr_NoMemory;
507
508 return err;
509 }
510
511
ServiceRegisterReply(DNSServiceRef sdRef _UNUSED,DNSServiceFlags flags,DNSServiceErrorType errorCode,const char * serviceName,const char * regType,const char * domain,void * context)512 static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags,
513 DNSServiceErrorType errorCode, const char *serviceName,
514 const char *regType, const char *domain, void *context)
515 {
516 OpContext *pContext = (OpContext*) context;
517
518 SetupCallbackState( &pContext->Env);
519
520 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
521 {
522 if ( errorCode == kDNSServiceErr_NoError)
523 {
524 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
525 pContext->JavaObj, flags,
526 (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
527 (*pContext->Env)->NewStringUTF( pContext->Env, regType),
528 (*pContext->Env)->NewStringUTF( pContext->Env, domain));
529 }
530 else
531 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
532 }
533 TeardownCallbackState();
534 }
535
Java_com_apple_dnssd_AppleRegistration_BeginRegister(JNIEnv * pEnv,jobject pThis,jint ifIndex,jint flags,jstring serviceName,jstring regType,jstring domain,jstring host,jint port,jbyteArray txtRecord)536 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv *pEnv, jobject pThis,
537 jint ifIndex, jint flags, jstring serviceName, jstring regType,
538 jstring domain, jstring host, jint port, jbyteArray txtRecord)
539 {
540 //syslog(LOG_ERR, "BR");
541 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
542 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
543 OpContext *pContext = NULL;
544 DNSServiceErrorType err = kDNSServiceErr_NoError;
545 jbyte *pBytes;
546 jsize numBytes;
547
548 //syslog(LOG_ERR, "BR: contextField %d", contextField);
549
550 if ( contextField != 0)
551 pContext = NewContext( pEnv, pThis, "serviceRegistered",
552 "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
553 else
554 err = kDNSServiceErr_BadParam;
555
556 if ( pContext != NULL)
557 {
558 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
559 const char *regStr = SafeGetUTFChars( pEnv, regType);
560 const char *domainStr = SafeGetUTFChars( pEnv, domain);
561 const char *hostStr = SafeGetUTFChars( pEnv, host);
562
563 //syslog(LOG_ERR, "BR: regStr %s", regStr);
564
565 // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
566 // big-endian number into a 16-bit pattern here.
567 uint16_t portBits = port;
568 portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1];
569
570 pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
571 numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
572
573 err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
574 domainStr, hostStr, portBits,
575 numBytes, pBytes, ServiceRegisterReply, pContext);
576 if ( err == kDNSServiceErr_NoError)
577 {
578 (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
579 }
580
581 if ( pBytes != NULL)
582 (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
583
584 SafeReleaseUTFChars( pEnv, serviceName, servStr);
585 SafeReleaseUTFChars( pEnv, regType, regStr);
586 SafeReleaseUTFChars( pEnv, domain, domainStr);
587 SafeReleaseUTFChars( pEnv, host, hostStr);
588 }
589 else
590 err = kDNSServiceErr_NoMemory;
591
592 return err;
593 }
594
Java_com_apple_dnssd_AppleRegistration_AddRecord(JNIEnv * pEnv,jobject pThis,jint flags,jint rrType,jbyteArray rData,jint ttl,jobject destObj)595 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis,
596 jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj)
597 {
598 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
599 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
600 jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
601 jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
602 OpContext *pContext = NULL;
603 DNSServiceErrorType err = kDNSServiceErr_NoError;
604 jbyte *pBytes;
605 jsize numBytes;
606 DNSRecordRef recRef;
607
608 if ( contextField != 0)
609 pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
610 if ( pContext == NULL || pContext->ServiceRef == NULL)
611 return kDNSServiceErr_BadParam;
612
613 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
614 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
615
616 err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
617 if ( err == kDNSServiceErr_NoError)
618 {
619 (*pEnv)->SetLongField( pEnv, destObj, recField, (jlong) recRef);
620 }
621
622 if ( pBytes != NULL)
623 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
624
625 return err;
626 }
627
Java_com_apple_dnssd_AppleDNSRecord_Update(JNIEnv * pEnv,jobject pThis,jint flags,jbyteArray rData,jint ttl)628 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis,
629 jint flags, jbyteArray rData, jint ttl)
630 {
631 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
632 jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
633 jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
634 OpContext *pContext = NULL;
635 DNSServiceErrorType err = kDNSServiceErr_NoError;
636 jbyte *pBytes;
637 jsize numBytes;
638 DNSRecordRef recRef = NULL;
639
640 if ( ownerField != 0)
641 {
642 jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
643 jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
644 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
645 if ( contextField != 0)
646 pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, ownerObj, contextField);
647 }
648 if ( recField != 0)
649 recRef = (DNSRecordRef) (*pEnv)->GetLongField( pEnv, pThis, recField);
650 if ( pContext == NULL || pContext->ServiceRef == NULL)
651 return kDNSServiceErr_BadParam;
652
653 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
654 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
655
656 err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
657
658 if ( pBytes != NULL)
659 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
660
661 return err;
662 }
663
Java_com_apple_dnssd_AppleDNSRecord_Remove(JNIEnv * pEnv,jobject pThis)664 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis)
665 {
666 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
667 jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
668 jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
669 OpContext *pContext = NULL;
670 DNSServiceErrorType err = kDNSServiceErr_NoError;
671 DNSRecordRef recRef = NULL;
672
673 if ( ownerField != 0)
674 {
675 jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
676 jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
677 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
678 if ( contextField != 0)
679 pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, ownerObj, contextField);
680 }
681 if ( recField != 0)
682 recRef = (DNSRecordRef) (*pEnv)->GetLongField( pEnv, pThis, recField);
683 if ( pContext == NULL || pContext->ServiceRef == NULL)
684 return kDNSServiceErr_BadParam;
685
686 err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
687
688 return err;
689 }
690
691
Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection(JNIEnv * pEnv,jobject pThis)692 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis)
693 {
694 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
695 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
696 OpContext *pContext = NULL;
697 DNSServiceErrorType err = kDNSServiceErr_NoError;
698
699 if ( contextField != 0)
700 pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V");
701 else
702 err = kDNSServiceErr_BadParam;
703
704 if ( pContext != NULL)
705 {
706 err = DNSServiceCreateConnection( &pContext->ServiceRef);
707 if ( err == kDNSServiceErr_NoError)
708 {
709 (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
710 }
711 }
712 else
713 err = kDNSServiceErr_NoMemory;
714
715 return err;
716 }
717
718 struct RecordRegistrationRef
719 {
720 OpContext *Context;
721 jobject RecordObj;
722 };
723 typedef struct RecordRegistrationRef RecordRegistrationRef;
724
RegisterRecordReply(DNSServiceRef sdRef _UNUSED,DNSRecordRef recordRef _UNUSED,DNSServiceFlags flags,DNSServiceErrorType errorCode,void * context)725 static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED,
726 DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags,
727 DNSServiceErrorType errorCode, void *context)
728 {
729 RecordRegistrationRef *regEnvelope = (RecordRegistrationRef*) context;
730 OpContext *pContext = regEnvelope->Context;
731
732 SetupCallbackState( &pContext->Env);
733
734 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
735 {
736 if ( errorCode == kDNSServiceErr_NoError)
737 {
738 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
739 regEnvelope->RecordObj, flags);
740 }
741 else
742 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
743 }
744
745 (*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj);
746 free( regEnvelope);
747
748 TeardownCallbackState();
749 }
750
Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord(JNIEnv * pEnv,jobject pThis,jint flags,jint ifIndex,jstring fullname,jint rrType,jint rrClass,jbyteArray rData,jint ttl,jobject destObj)751 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord( JNIEnv *pEnv, jobject pThis,
752 jint flags, jint ifIndex, jstring fullname, jint rrType, jint rrClass,
753 jbyteArray rData, jint ttl, jobject destObj)
754 {
755 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
756 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
757 jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
758 jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
759 const char *nameStr = SafeGetUTFChars( pEnv, fullname);
760 OpContext *pContext = NULL;
761 DNSServiceErrorType err = kDNSServiceErr_NoError;
762 jbyte *pBytes;
763 jsize numBytes;
764 DNSRecordRef recRef;
765 RecordRegistrationRef *regEnvelope;
766
767 if ( contextField != 0)
768 pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
769 if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL)
770 return kDNSServiceErr_BadParam;
771
772 regEnvelope = calloc( 1, sizeof *regEnvelope);
773 if ( regEnvelope == NULL)
774 return kDNSServiceErr_NoMemory;
775 regEnvelope->Context = pContext;
776 regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache
777
778 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
779 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
780
781 err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex,
782 nameStr, rrType, rrClass, numBytes, pBytes, ttl,
783 RegisterRecordReply, regEnvelope);
784
785 if ( err == kDNSServiceErr_NoError)
786 {
787 (*pEnv)->SetLongField( pEnv, destObj, recField, (jlong) recRef);
788 }
789 else
790 {
791 if ( regEnvelope->RecordObj != NULL)
792 (*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj);
793 free( regEnvelope);
794 }
795
796 if ( pBytes != NULL)
797 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
798
799 SafeReleaseUTFChars( pEnv, fullname, nameStr);
800
801 return err;
802 }
803
804
ServiceQueryReply(DNSServiceRef sdRef _UNUSED,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)805 static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
806 DNSServiceErrorType errorCode, const char *serviceName,
807 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen,
808 const void *rdata, uint32_t ttl, void *context)
809 {
810 OpContext *pContext = (OpContext*) context;
811 jbyteArray rDataObj;
812 jbyte *pBytes;
813
814 SetupCallbackState( &pContext->Env);
815
816 if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
817 NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
818 {
819 if ( errorCode == kDNSServiceErr_NoError)
820 {
821 // Initialize rDataObj with contents of rdata
822 pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL);
823 memcpy( pBytes, rdata, rdlen);
824 (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT);
825
826 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
827 pContext->JavaObj, flags, interfaceIndex,
828 (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
829 rrtype, rrclass, rDataObj, ttl);
830 }
831 else
832 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
833 }
834 TeardownCallbackState();
835 }
836
Java_com_apple_dnssd_AppleQuery_CreateQuery(JNIEnv * pEnv,jobject pThis,jint flags,jint ifIndex,jstring serviceName,jint rrtype,jint rrclass)837 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis,
838 jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass)
839 {
840 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
841 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
842 OpContext *pContext = NULL;
843 DNSServiceErrorType err = kDNSServiceErr_NoError;
844
845 if ( contextField != 0)
846 pContext = NewContext( pEnv, pThis, "queryAnswered",
847 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
848 else
849 err = kDNSServiceErr_BadParam;
850
851 if ( pContext != NULL)
852 {
853 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
854
855 err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
856 rrtype, rrclass, ServiceQueryReply, pContext);
857 if ( err == kDNSServiceErr_NoError)
858 {
859 (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
860 }
861
862 SafeReleaseUTFChars( pEnv, serviceName, servStr);
863 }
864 else
865 err = kDNSServiceErr_NoMemory;
866
867 return err;
868 }
869
870
DomainEnumReply(DNSServiceRef sdRef _UNUSED,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * replyDomain,void * context)871 static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
872 DNSServiceErrorType errorCode, const char *replyDomain, void *context)
873 {
874 OpContext *pContext = (OpContext*) context;
875
876 SetupCallbackState( &pContext->Env);
877
878 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
879 {
880 if ( errorCode == kDNSServiceErr_NoError)
881 {
882 (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
883 ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
884 pContext->JavaObj, flags, interfaceIndex,
885 (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
886 }
887 else
888 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
889 }
890 TeardownCallbackState();
891 }
892
Java_com_apple_dnssd_AppleDomainEnum_BeginEnum(JNIEnv * pEnv,jobject pThis,jint flags,jint ifIndex)893 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
894 jint flags, jint ifIndex)
895 {
896 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
897 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
898 OpContext *pContext = NULL;
899 DNSServiceErrorType err = kDNSServiceErr_NoError;
900
901 if ( contextField != 0)
902 pContext = NewContext( pEnv, pThis, "domainFound",
903 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
904 else
905 err = kDNSServiceErr_BadParam;
906
907 if ( pContext != NULL)
908 {
909 pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
910 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
911 "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
912
913 err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
914 DomainEnumReply, pContext);
915 if ( err == kDNSServiceErr_NoError)
916 {
917 (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
918 }
919 }
920 else
921 err = kDNSServiceErr_NoMemory;
922
923 return err;
924 }
925
926
Java_com_apple_dnssd_AppleDNSSD_ConstructName(JNIEnv * pEnv,jobject pThis _UNUSED,jstring serviceName,jstring regtype,jstring domain,jobjectArray pOut)927 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
928 jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
929 {
930 DNSServiceErrorType err = kDNSServiceErr_NoError;
931 const char *nameStr = SafeGetUTFChars( pEnv, serviceName);
932 const char *regStr = SafeGetUTFChars( pEnv, regtype);
933 const char *domStr = SafeGetUTFChars( pEnv, domain);
934 char buff[ kDNSServiceMaxDomainName + 1];
935
936 err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
937
938 if ( err == kDNSServiceErr_NoError)
939 {
940 // pOut is expected to be a String[1] array.
941 (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
942 }
943
944 SafeReleaseUTFChars( pEnv, serviceName, nameStr);
945 SafeReleaseUTFChars( pEnv, regtype, regStr);
946 SafeReleaseUTFChars( pEnv, domain, domStr);
947
948 return err;
949 }
950
Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord(JNIEnv * pEnv,jobject pThis _UNUSED,jint flags,jint ifIndex,jstring fullName,jint rrtype,jint rrclass,jbyteArray rdata)951 JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED,
952 jint flags, jint ifIndex, jstring fullName,
953 jint rrtype, jint rrclass, jbyteArray rdata)
954 {
955 jbyte *pBytes;
956 jsize numBytes;
957 const char *nameStr = SafeGetUTFChars( pEnv, fullName);
958
959 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
960 numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
961
962 DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
963
964 if ( pBytes != NULL)
965 (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
966
967 SafeReleaseUTFChars( pEnv, fullName, nameStr);
968 }
969
970 #define LOCAL_ONLY_NAME "loo"
971
Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex(JNIEnv * pEnv,jobject pThis _UNUSED,jint ifIndex)972 JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
973 jint ifIndex)
974 {
975 char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
976
977 if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
978 p = if_indextoname( ifIndex, nameBuff );
979
980 return (*pEnv)->NewStringUTF( pEnv, p);
981 }
982
983
Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName(JNIEnv * pEnv,jobject pThis _UNUSED,jstring ifName)984 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED,
985 jstring ifName)
986 {
987 uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
988 const char *nameStr = SafeGetUTFChars( pEnv, ifName);
989
990 if (strcmp(nameStr, LOCAL_ONLY_NAME))
991 ifIndex = if_nametoindex( nameStr);
992
993 SafeReleaseUTFChars( pEnv, ifName, nameStr);
994
995 return ifIndex;
996 }
997
998
999 #if defined(_WIN32)
1000 static char*
if_indextoname(DWORD ifIndex,char * nameBuff)1001 if_indextoname( DWORD ifIndex, char * nameBuff)
1002 {
1003 PIP_ADAPTER_INFO pAdapterInfo = NULL;
1004 PIP_ADAPTER_INFO pAdapter = NULL;
1005 DWORD dwRetVal = 0;
1006 char * ifName = NULL;
1007 ULONG ulOutBufLen = 0;
1008
1009 if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
1010 {
1011 goto exit;
1012 }
1013
1014 pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
1015
1016 if (pAdapterInfo == NULL)
1017 {
1018 goto exit;
1019 }
1020
1021 dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
1022
1023 if (dwRetVal != NO_ERROR)
1024 {
1025 goto exit;
1026 }
1027
1028 pAdapter = pAdapterInfo;
1029 while (pAdapter)
1030 {
1031 if (pAdapter->Index == ifIndex)
1032 {
1033 // It would be better if we passed in the length of nameBuff to this
1034 // function, so we would have absolute certainty that no buffer
1035 // overflows would occur. Buffer overflows *shouldn't* occur because
1036 // nameBuff is of size MAX_ADAPTER_NAME_LENGTH.
1037 strcpy( nameBuff, pAdapter->AdapterName );
1038 ifName = nameBuff;
1039 break;
1040 }
1041
1042 pAdapter = pAdapter->Next;
1043 }
1044
1045 exit:
1046
1047 if (pAdapterInfo != NULL)
1048 {
1049 free( pAdapterInfo );
1050 pAdapterInfo = NULL;
1051 }
1052
1053 return ifName;
1054 }
1055
1056
1057 static DWORD
if_nametoindex(const char * nameStr)1058 if_nametoindex( const char * nameStr )
1059 {
1060 PIP_ADAPTER_INFO pAdapterInfo = NULL;
1061 PIP_ADAPTER_INFO pAdapter = NULL;
1062 DWORD dwRetVal = 0;
1063 DWORD ifIndex = 0;
1064 ULONG ulOutBufLen = 0;
1065
1066 if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
1067 {
1068 goto exit;
1069 }
1070
1071 pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
1072
1073 if (pAdapterInfo == NULL)
1074 {
1075 goto exit;
1076 }
1077
1078 dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
1079
1080 if (dwRetVal != NO_ERROR)
1081 {
1082 goto exit;
1083 }
1084
1085 pAdapter = pAdapterInfo;
1086 while (pAdapter)
1087 {
1088 if (strcmp(pAdapter->AdapterName, nameStr) == 0)
1089 {
1090 ifIndex = pAdapter->Index;
1091 break;
1092 }
1093
1094 pAdapter = pAdapter->Next;
1095 }
1096
1097 exit:
1098
1099 if (pAdapterInfo != NULL)
1100 {
1101 free( pAdapterInfo );
1102 pAdapterInfo = NULL;
1103 }
1104
1105 return ifIndex;
1106 }
1107 #endif
1108