2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: JNISupport.c,v $
26 Revision 1.9 2004/12/11 03:01:00 rpantos
27 <rdar://problem/3907498> Java DNSRecord API should be cleaned up
29 Revision 1.8 2004/11/30 23:51:05 cheshire
30 Remove double semicolons
32 Revision 1.7 2004/11/23 08:12:04 shersche
33 Implement if_nametoindex and if_indextoname for Win32 platforms
35 Revision 1.6 2004/11/23 03:41:14 cheshire
36 Change JNISupport.c to call if_indextoname & if_nametoindex directly.
37 (May require some additional glue code to work on Windows.)
39 Revision 1.5 2004/11/17 17:07:44 cheshire
40 Updated comment about AUTO_CALLBACKS
42 Revision 1.4 2004/11/12 03:23:09 rpantos
43 rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
45 Revision 1.3 2004/06/18 04:44:17 rpantos
46 Adapt to API unification on Windows
48 Revision 1.2 2004/05/28 23:34:42 ksekar
49 <rdar://problem/3672903>: Java project build errors
51 Revision 1.1 2004/04/30 16:29:35 rpantos
55 This file contains the platform support for DNSSD and related Java classes.
56 It is used to shim through to the underlying <dns_sd.h> API.
59 // AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
60 // callbacks automatically (as in the early Windows prototypes).
61 // AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
62 // invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.).
63 // (Invoking callbacks automatically on a different thread sounds attractive, but while
64 // the client gains by not needing to add an event source to its main event loop, it loses
65 // by being forced to deal with concurrency and locking, which can be a bigger burden.)
66 #ifndef AUTO_CALLBACKS
67 #define AUTO_CALLBACKS 0
74 #include <sys/types.h>
75 #include <sys/select.h>
77 #endif // AUTO_CALLBACKS
87 static char * if_indextoname( DWORD ifIndex
, char * nameBuff
);
88 static DWORD
if_nametoindex( const char * nameStr
);
89 #define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
91 #include <sys/socket.h>
96 #include "DNSSD.java.h"
98 // convenience definition
100 #define _UNUSED __attribute__ ((unused))
106 kInterfaceVersion
= 1 // Must match version in .jar file
109 typedef struct OpContext OpContext
;
113 DNSServiceRef ServiceRef
;
121 // For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
123 JavaVM
*gJavaVM
= NULL
;
127 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv
*pEnv
, jclass cls
,
130 /* Ensure that caller & interface versions match. */
131 if ( callerVersion
!= kInterfaceVersion
)
132 return kDNSServiceErr_Incompatible
;
138 if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM
, 1, &numVMs
))
139 return kDNSServiceErr_BadState
;
143 // Set AppleDNSSD.hasAutoCallbacks
146 jboolean hasAutoC
= JNI_TRUE
;
148 jboolean hasAutoC
= JNI_FALSE
;
150 jfieldID hasAutoCField
= (*pEnv
)->GetStaticFieldID( pEnv
, cls
, "hasAutoCallbacks", "Z");
151 (*pEnv
)->SetStaticBooleanField( pEnv
, cls
, hasAutoCField
, hasAutoC
);
154 return kDNSServiceErr_NoError
;
158 static const char* SafeGetUTFChars( JNIEnv
*pEnv
, jstring str
)
159 // Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
161 return str
!= NULL
? (*pEnv
)->GetStringUTFChars( pEnv
, str
, 0) : NULL
;
164 static void SafeReleaseUTFChars( JNIEnv
*pEnv
, jstring str
, const char *buff
)
165 // Wrapper for JNI GetStringUTFChars() that handles null str.
168 (*pEnv
)->ReleaseStringUTFChars( pEnv
, str
, buff
);
173 static void SetupCallbackState( JNIEnv
**ppEnv
)
175 (*gJavaVM
)->AttachCurrentThread( gJavaVM
, (void**) ppEnv
, NULL
);
178 static void TeardownCallbackState( void )
180 (*gJavaVM
)->DetachCurrentThread( gJavaVM
);
183 #else // AUTO_CALLBACKS
185 static void SetupCallbackState( JNIEnv
**ppEnv _UNUSED
)
187 // No setup necessary if ProcessResults() has been called
190 static void TeardownCallbackState( void )
192 // No teardown necessary if ProcessResults() has been called
194 #endif // AUTO_CALLBACKS
197 static OpContext
*NewContext( JNIEnv
*pEnv
, jobject owner
, const char *ownerClass
,
198 const char *callbackName
, const char *callbackSig
)
199 // Create and initialize a new OpContext.
201 OpContext
*pContext
= (OpContext
*) malloc( sizeof *pContext
);
203 if ( pContext
!= NULL
)
205 jfieldID clientField
= (*pEnv
)->GetFieldID( pEnv
, (*pEnv
)->GetObjectClass( pEnv
, owner
),
206 "fClient", ownerClass
);
208 pContext
->JavaObj
= (*pEnv
)->NewWeakGlobalRef( pEnv
, owner
); // must convert local ref to global to cache;
209 pContext
->ClientObj
= (*pEnv
)->GetObjectField( pEnv
, owner
, clientField
);
210 pContext
->ClientObj
= (*pEnv
)->NewWeakGlobalRef( pEnv
, pContext
->ClientObj
); // must convert local ref to global to cache
211 pContext
->Callback
= (*pEnv
)->GetMethodID( pEnv
,
212 (*pEnv
)->GetObjectClass( pEnv
, pContext
->ClientObj
),
213 callbackName
, callbackSig
);
214 pContext
->Callback2
= NULL
; // not always used
221 static void ReportError( JNIEnv
*pEnv
, jobject target
, jobject service
, DNSServiceErrorType err
)
222 // Invoke operationFailed() method on target with err.
224 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, target
);
225 jmethodID opFailed
= (*pEnv
)->GetMethodID( pEnv
, cls
, "operationFailed",
226 "(Lcom/apple/dnssd/DNSSDService;I)V");
228 (*pEnv
)->CallVoidMethod( pEnv
, target
, opFailed
, service
, err
);
231 JNIEXPORT
void JNICALL
Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv
*pEnv
, jobject pThis
)
232 /* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
234 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
235 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
237 if ( contextField
!= 0)
239 OpContext
*pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
240 if ( pContext
!= NULL
)
242 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, 0);
243 if ( pContext
->ServiceRef
!= NULL
)
244 DNSServiceRefDeallocate( pContext
->ServiceRef
);
246 (*pEnv
)->DeleteWeakGlobalRef( pEnv
, pContext
->JavaObj
);
247 (*pEnv
)->DeleteWeakGlobalRef( pEnv
, pContext
->ClientObj
);
254 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv
*pEnv
, jobject pThis
, jint msTimeout
)
255 /* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */
258 return -1; // BlockForData() not supported with AUTO_CALLBACKS
259 #else // AUTO_CALLBACKS
260 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
261 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
264 if ( contextField
!= 0)
266 OpContext
*pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
267 if ( pContext
!= NULL
)
270 int sd
= DNSServiceRefSockFD( pContext
->ServiceRef
);
271 struct timeval timeout
= { msTimeout
/ 1000, 10 * (msTimeout
% 1000) };
272 struct timeval
*pTimeout
= msTimeout
== -1 ? NULL
: &timeout
;
275 FD_SET( sd
, &readFDs
);
277 rc
= select( sd
+ 1, &readFDs
, (fd_set
*) NULL
, (fd_set
*) NULL
, pTimeout
);
282 #endif // AUTO_CALLBACKS
286 JNIEXPORT
void JNICALL
Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv
*pEnv
, jobject pThis
)
287 /* Call through to DNSServiceProcessResult() while data remains on socket. */
289 #if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
291 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
292 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
293 OpContext
*pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
295 if ( pContext
!= NULL
)
297 int sd
= DNSServiceRefSockFD( pContext
->ServiceRef
);
299 struct timeval zeroTimeout
= { 0, 0 };
301 pContext
->Env
= pEnv
;
304 FD_SET( sd
, &readFDs
);
306 while ( 0 < select( sd
+ 1, &readFDs
, (fd_set
*) NULL
, (fd_set
*) NULL
, &zeroTimeout
))
308 DNSServiceProcessResult( pContext
->ServiceRef
);
311 #endif // AUTO_CALLBACKS
315 static void DNSSD_API
ServiceBrowseReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
316 DNSServiceErrorType errorCode
, const char *serviceName
, const char *regtype
,
317 const char *replyDomain
, void *context
)
319 OpContext
*pContext
= (OpContext
*) context
;
321 SetupCallbackState( &pContext
->Env
);
323 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
)
325 if ( errorCode
== kDNSServiceErr_NoError
)
327 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
,
328 ( flags
& kDNSServiceFlagsAdd
) != 0 ? pContext
->Callback
: pContext
->Callback2
,
329 pContext
->JavaObj
, flags
, interfaceIndex
,
330 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, serviceName
),
331 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, regtype
),
332 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, replyDomain
));
335 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
338 TeardownCallbackState();
341 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv
*pEnv
, jobject pThis
,
342 jint flags
, jint ifIndex
, jstring regType
, jstring domain
)
344 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
345 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
346 OpContext
*pContext
= NULL
;
347 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
349 if ( contextField
!= 0)
350 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/BrowseListener;", "serviceFound",
351 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
353 err
= kDNSServiceErr_BadParam
;
355 if ( pContext
!= NULL
)
357 const char *regStr
= SafeGetUTFChars( pEnv
, regType
);
358 const char *domainStr
= SafeGetUTFChars( pEnv
, domain
);
360 pContext
->Callback2
= (*pEnv
)->GetMethodID( pEnv
,
361 (*pEnv
)->GetObjectClass( pEnv
, pContext
->ClientObj
),
362 "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
364 err
= DNSServiceBrowse( &pContext
->ServiceRef
, flags
, ifIndex
, regStr
, domainStr
, ServiceBrowseReply
, pContext
);
365 if ( err
== kDNSServiceErr_NoError
)
367 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
370 SafeReleaseUTFChars( pEnv
, regType
, regStr
);
371 SafeReleaseUTFChars( pEnv
, domain
, domainStr
);
374 err
= kDNSServiceErr_NoMemory
;
380 static void DNSSD_API
ServiceResolveReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
381 DNSServiceErrorType errorCode
, const char *fullname
, const char *hosttarget
,
382 uint16_t port
, uint16_t txtLen
, const char *txtRecord
, void *context
)
384 OpContext
*pContext
= (OpContext
*) context
;
391 SetupCallbackState( &pContext
->Env
);
393 txtCls
= (*pContext
->Env
)->FindClass( pContext
->Env
, "com/apple/dnssd/TXTRecord");
394 txtCtor
= (*pContext
->Env
)->GetMethodID( pContext
->Env
, txtCls
, "<init>", "([B)V");
396 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
&& txtCtor
!= NULL
&&
397 NULL
!= ( txtBytes
= (*pContext
->Env
)->NewByteArray( pContext
->Env
, txtLen
)))
399 if ( errorCode
== kDNSServiceErr_NoError
)
401 // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
402 // pattern into a number here.
403 port
= ( ((unsigned char*) &port
)[0] << 8) | ((unsigned char*) &port
)[1];
405 // Initialize txtBytes with contents of txtRecord
406 pBytes
= (*pContext
->Env
)->GetByteArrayElements( pContext
->Env
, txtBytes
, NULL
);
407 memcpy( pBytes
, txtRecord
, txtLen
);
408 (*pContext
->Env
)->ReleaseByteArrayElements( pContext
->Env
, txtBytes
, pBytes
, JNI_COMMIT
);
410 // Construct txtObj with txtBytes
411 txtObj
= (*pContext
->Env
)->NewObject( pContext
->Env
, txtCls
, txtCtor
, txtBytes
);
412 (*pContext
->Env
)->DeleteLocalRef( pContext
->Env
, txtBytes
);
414 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
, pContext
->Callback
,
415 pContext
->JavaObj
, flags
, interfaceIndex
,
416 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, fullname
),
417 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, hosttarget
),
421 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
424 TeardownCallbackState();
427 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv
*pEnv
, jobject pThis
,
428 jint flags
, jint ifIndex
, jstring serviceName
, jstring regType
, jstring domain
)
430 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
431 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
432 OpContext
*pContext
= NULL
;
433 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
435 if ( contextField
!= 0)
436 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/ResolveListener;", "serviceResolved",
437 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
439 err
= kDNSServiceErr_BadParam
;
441 if ( pContext
!= NULL
)
443 const char *servStr
= SafeGetUTFChars( pEnv
, serviceName
);
444 const char *regStr
= SafeGetUTFChars( pEnv
, regType
);
445 const char *domainStr
= SafeGetUTFChars( pEnv
, domain
);
447 err
= DNSServiceResolve( &pContext
->ServiceRef
, flags
, ifIndex
,
448 servStr
, regStr
, domainStr
, ServiceResolveReply
, pContext
);
449 if ( err
== kDNSServiceErr_NoError
)
451 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
454 SafeReleaseUTFChars( pEnv
, serviceName
, servStr
);
455 SafeReleaseUTFChars( pEnv
, regType
, regStr
);
456 SafeReleaseUTFChars( pEnv
, domain
, domainStr
);
459 err
= kDNSServiceErr_NoMemory
;
465 static void DNSSD_API
ServiceRegisterReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
,
466 DNSServiceErrorType errorCode
, const char *fullname
,
467 const char *regType
, const char *domain
, void *context
)
469 OpContext
*pContext
= (OpContext
*) context
;
471 SetupCallbackState( &pContext
->Env
);
473 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
)
475 if ( errorCode
== kDNSServiceErr_NoError
)
477 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
, pContext
->Callback
,
478 pContext
->JavaObj
, flags
,
479 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, fullname
),
480 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, regType
),
481 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, domain
));
484 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
486 TeardownCallbackState();
489 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv
*pEnv
, jobject pThis
,
490 jint ifIndex
, jint flags
, jstring serviceName
, jstring regType
,
491 jstring domain
, jstring host
, jint port
, jbyteArray txtRecord
)
493 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
494 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
495 OpContext
*pContext
= NULL
;
496 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
500 if ( contextField
!= 0)
501 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/RegisterListener;", "serviceRegistered",
502 "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
504 err
= kDNSServiceErr_BadParam
;
506 if ( pContext
!= NULL
)
508 const char *servStr
= SafeGetUTFChars( pEnv
, serviceName
);
509 const char *regStr
= SafeGetUTFChars( pEnv
, regType
);
510 const char *domainStr
= SafeGetUTFChars( pEnv
, domain
);
511 const char *hostStr
= SafeGetUTFChars( pEnv
, host
);
513 // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
514 // big-endian number into a 16-bit pattern here.
515 uint16_t portBits
= port
;
516 portBits
= ( ((unsigned char*) &portBits
)[0] << 8) | ((unsigned char*) &portBits
)[1];
518 pBytes
= txtRecord
? (*pEnv
)->GetByteArrayElements( pEnv
, txtRecord
, NULL
) : NULL
;
519 numBytes
= txtRecord
? (*pEnv
)->GetArrayLength( pEnv
, txtRecord
) : 0;
521 err
= DNSServiceRegister( &pContext
->ServiceRef
, flags
, ifIndex
, servStr
, regStr
,
522 domainStr
, hostStr
, portBits
,
523 numBytes
, pBytes
, ServiceRegisterReply
, pContext
);
524 if ( err
== kDNSServiceErr_NoError
)
526 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
530 (*pEnv
)->ReleaseByteArrayElements( pEnv
, txtRecord
, pBytes
, 0);
532 SafeReleaseUTFChars( pEnv
, serviceName
, servStr
);
533 SafeReleaseUTFChars( pEnv
, regType
, regStr
);
534 SafeReleaseUTFChars( pEnv
, domain
, domainStr
);
535 SafeReleaseUTFChars( pEnv
, host
, hostStr
);
538 err
= kDNSServiceErr_NoMemory
;
543 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv
*pEnv
, jobject pThis
,
544 jint flags
, jint rrType
, jbyteArray rData
, jint ttl
, jobject destObj
)
546 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
547 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
548 jclass destCls
= (*pEnv
)->GetObjectClass( pEnv
, destObj
);
549 jfieldID recField
= (*pEnv
)->GetFieldID( pEnv
, destCls
, "fRecord", "I");
550 OpContext
*pContext
= NULL
;
551 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
556 if ( contextField
!= 0)
557 pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
558 if ( pContext
== NULL
|| pContext
->ServiceRef
== NULL
)
559 return kDNSServiceErr_BadParam
;
561 pBytes
= (*pEnv
)->GetByteArrayElements( pEnv
, rData
, NULL
);
562 numBytes
= (*pEnv
)->GetArrayLength( pEnv
, rData
);
564 err
= DNSServiceAddRecord( pContext
->ServiceRef
, &recRef
, flags
, rrType
, numBytes
, pBytes
, ttl
);
565 if ( err
== kDNSServiceErr_NoError
)
567 (*pEnv
)->SetIntField( pEnv
, destObj
, recField
, (jint
) recRef
);
571 (*pEnv
)->ReleaseByteArrayElements( pEnv
, rData
, pBytes
, 0);
576 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv
*pEnv
, jobject pThis
,
577 jint flags
, jbyteArray rData
, jint ttl
)
579 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
580 jfieldID ownerField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fOwner", "Lcom/apple/dnssd/AppleService;");
581 jfieldID recField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fRecord", "I");
582 OpContext
*pContext
= NULL
;
583 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
586 DNSRecordRef recRef
= NULL
;
588 if ( ownerField
!= 0)
590 jobject ownerObj
= (*pEnv
)->GetObjectField( pEnv
, pThis
, ownerField
);
591 jclass ownerClass
= (*pEnv
)->GetObjectClass( pEnv
, ownerObj
);
592 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, ownerClass
, "fNativeContext", "I");
593 if ( contextField
!= 0)
594 pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, ownerObj
, contextField
);
597 recRef
= (DNSRecordRef
) (*pEnv
)->GetIntField( pEnv
, pThis
, recField
);
598 if ( pContext
== NULL
|| pContext
->ServiceRef
== NULL
)
599 return kDNSServiceErr_BadParam
;
601 pBytes
= (*pEnv
)->GetByteArrayElements( pEnv
, rData
, NULL
);
602 numBytes
= (*pEnv
)->GetArrayLength( pEnv
, rData
);
604 err
= DNSServiceUpdateRecord( pContext
->ServiceRef
, recRef
, flags
, numBytes
, pBytes
, ttl
);
607 (*pEnv
)->ReleaseByteArrayElements( pEnv
, rData
, pBytes
, 0);
612 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv
*pEnv
, jobject pThis
)
614 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
615 jfieldID ownerField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fOwner", "Lcom/apple/dnssd/AppleService;");
616 jfieldID recField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fRecord", "I");
617 OpContext
*pContext
= NULL
;
618 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
619 DNSRecordRef recRef
= NULL
;
621 if ( ownerField
!= 0)
623 jobject ownerObj
= (*pEnv
)->GetObjectField( pEnv
, pThis
, ownerField
);
624 jclass ownerClass
= (*pEnv
)->GetObjectClass( pEnv
, ownerObj
);
625 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, ownerClass
, "fNativeContext", "I");
626 if ( contextField
!= 0)
627 pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, ownerObj
, contextField
);
630 recRef
= (DNSRecordRef
) (*pEnv
)->GetIntField( pEnv
, pThis
, recField
);
631 if ( pContext
== NULL
|| pContext
->ServiceRef
== NULL
)
632 return kDNSServiceErr_BadParam
;
634 err
= DNSServiceRemoveRecord( pContext
->ServiceRef
, recRef
, 0);
640 static void DNSSD_API
ServiceQueryReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
641 DNSServiceErrorType errorCode
, const char *serviceName
,
642 uint16_t rrtype
, uint16_t rrclass
, uint16_t rdlen
,
643 const void *rdata
, uint32_t ttl
, void *context
)
645 OpContext
*pContext
= (OpContext
*) context
;
649 SetupCallbackState( &pContext
->Env
);
651 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
&&
652 NULL
!= ( rDataObj
= (*pContext
->Env
)->NewByteArray( pContext
->Env
, rdlen
)))
654 if ( errorCode
== kDNSServiceErr_NoError
)
656 // Initialize rDataObj with contents of rdata
657 pBytes
= (*pContext
->Env
)->GetByteArrayElements( pContext
->Env
, rDataObj
, NULL
);
658 memcpy( pBytes
, rdata
, rdlen
);
659 (*pContext
->Env
)->ReleaseByteArrayElements( pContext
->Env
, rDataObj
, pBytes
, JNI_COMMIT
);
661 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
, pContext
->Callback
,
662 pContext
->JavaObj
, flags
, interfaceIndex
,
663 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, serviceName
),
664 rrtype
, rrclass
, rDataObj
, ttl
);
667 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
669 TeardownCallbackState();
672 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv
*pEnv
, jobject pThis
,
673 jint flags
, jint ifIndex
, jstring serviceName
, jint rrtype
, jint rrclass
)
675 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
676 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
677 OpContext
*pContext
= NULL
;
678 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
680 if ( contextField
!= 0)
681 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/QueryListener;", "queryAnswered",
682 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
684 err
= kDNSServiceErr_BadParam
;
686 if ( pContext
!= NULL
)
688 const char *servStr
= SafeGetUTFChars( pEnv
, serviceName
);
690 err
= DNSServiceQueryRecord( &pContext
->ServiceRef
, flags
, ifIndex
, servStr
,
691 rrtype
, rrclass
, ServiceQueryReply
, pContext
);
692 if ( err
== kDNSServiceErr_NoError
)
694 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
697 SafeReleaseUTFChars( pEnv
, serviceName
, servStr
);
700 err
= kDNSServiceErr_NoMemory
;
706 static void DNSSD_API
DomainEnumReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
707 DNSServiceErrorType errorCode
, const char *replyDomain
, void *context
)
709 OpContext
*pContext
= (OpContext
*) context
;
711 SetupCallbackState( &pContext
->Env
);
713 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
)
715 if ( errorCode
== kDNSServiceErr_NoError
)
717 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
,
718 ( flags
& kDNSServiceFlagsAdd
) != 0 ? pContext
->Callback
: pContext
->Callback2
,
719 pContext
->JavaObj
, flags
, interfaceIndex
,
720 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, replyDomain
));
723 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
725 TeardownCallbackState();
728 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv
*pEnv
, jobject pThis
,
729 jint flags
, jint ifIndex
)
731 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
732 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
733 OpContext
*pContext
= NULL
;
734 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
736 if ( contextField
!= 0)
737 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/DomainListener;", "domainFound",
738 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
740 err
= kDNSServiceErr_BadParam
;
742 if ( pContext
!= NULL
)
744 pContext
->Callback2
= (*pEnv
)->GetMethodID( pEnv
,
745 (*pEnv
)->GetObjectClass( pEnv
, pContext
->ClientObj
),
746 "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
748 err
= DNSServiceEnumerateDomains( &pContext
->ServiceRef
, flags
, ifIndex
,
749 DomainEnumReply
, pContext
);
750 if ( err
== kDNSServiceErr_NoError
)
752 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
756 err
= kDNSServiceErr_NoMemory
;
762 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv
*pEnv
, jobject pThis _UNUSED
,
763 jstring serviceName
, jstring regtype
, jstring domain
, jobjectArray pOut
)
765 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
766 const char *nameStr
= SafeGetUTFChars( pEnv
, serviceName
);
767 const char *regStr
= SafeGetUTFChars( pEnv
, regtype
);
768 const char *domStr
= SafeGetUTFChars( pEnv
, domain
);
769 char buff
[ kDNSServiceMaxDomainName
+ 1];
771 err
= DNSServiceConstructFullName( buff
, nameStr
, regStr
, domStr
);
773 if ( err
== kDNSServiceErr_NoError
)
775 // pOut is expected to be a String[1] array.
776 (*pEnv
)->SetObjectArrayElement( pEnv
, pOut
, 0, (*pEnv
)->NewStringUTF( pEnv
, buff
));
779 SafeReleaseUTFChars( pEnv
, serviceName
, nameStr
);
780 SafeReleaseUTFChars( pEnv
, regtype
, regStr
);
781 SafeReleaseUTFChars( pEnv
, domain
, domStr
);
786 JNIEXPORT
void JNICALL
Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv
*pEnv
, jobject pThis _UNUSED
,
787 jint flags
, jint ifIndex
, jstring fullName
,
788 jint rrtype
, jint rrclass
, jbyteArray rdata
)
792 const char *nameStr
= SafeGetUTFChars( pEnv
, fullName
);
794 pBytes
= (*pEnv
)->GetByteArrayElements( pEnv
, rdata
, NULL
);
795 numBytes
= (*pEnv
)->GetArrayLength( pEnv
, rdata
);
797 DNSServiceReconfirmRecord( flags
, ifIndex
, nameStr
, rrtype
, rrclass
, numBytes
, pBytes
);
800 (*pEnv
)->ReleaseByteArrayElements( pEnv
, rdata
, pBytes
, 0);
802 SafeReleaseUTFChars( pEnv
, fullName
, nameStr
);
805 #define LOCAL_ONLY_NAME "loo"
807 JNIEXPORT jstring JNICALL
Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv
*pEnv
, jobject pThis _UNUSED
,
810 char *p
= LOCAL_ONLY_NAME
, nameBuff
[IF_NAMESIZE
];
812 if (ifIndex
!= kDNSServiceInterfaceIndexLocalOnly
)
813 p
= if_indextoname( ifIndex
, nameBuff
);
815 return (*pEnv
)->NewStringUTF( pEnv
, p
);
819 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv
*pEnv
, jobject pThis _UNUSED
,
822 uint32_t ifIndex
= kDNSServiceInterfaceIndexLocalOnly
;
823 const char *nameStr
= SafeGetUTFChars( pEnv
, ifName
);
825 if (strcmp(nameStr
, LOCAL_ONLY_NAME
))
826 ifIndex
= if_nametoindex( nameStr
);
828 SafeReleaseUTFChars( pEnv
, ifName
, nameStr
);
836 if_indextoname( DWORD ifIndex
, char * nameBuff
)
838 PIP_ADAPTER_INFO pAdapterInfo
= NULL
;
839 PIP_ADAPTER_INFO pAdapter
= NULL
;
841 char * ifName
= NULL
;
842 ULONG ulOutBufLen
= 0;
844 if (GetAdaptersInfo( NULL
, &ulOutBufLen
) != ERROR_BUFFER_OVERFLOW
)
849 pAdapterInfo
= (IP_ADAPTER_INFO
*) malloc(ulOutBufLen
);
851 if (pAdapterInfo
== NULL
)
856 dwRetVal
= GetAdaptersInfo( pAdapterInfo
, &ulOutBufLen
);
858 if (dwRetVal
!= NO_ERROR
)
863 pAdapter
= pAdapterInfo
;
866 if (pAdapter
->Index
== ifIndex
)
868 // It would be better if we passed in the length of nameBuff to this
869 // function, so we would have absolute certainty that no buffer
870 // overflows would occur. Buffer overflows *shouldn't* occur because
871 // nameBuff is of size MAX_ADAPTER_NAME_LENGTH.
872 strcpy( nameBuff
, pAdapter
->AdapterName
);
877 pAdapter
= pAdapter
->Next
;
882 if (pAdapterInfo
!= NULL
)
884 free( pAdapterInfo
);
893 if_nametoindex( const char * nameStr
)
895 PIP_ADAPTER_INFO pAdapterInfo
= NULL
;
896 PIP_ADAPTER_INFO pAdapter
= NULL
;
899 ULONG ulOutBufLen
= 0;
901 if (GetAdaptersInfo( NULL
, &ulOutBufLen
) != ERROR_BUFFER_OVERFLOW
)
906 pAdapterInfo
= (IP_ADAPTER_INFO
*) malloc(ulOutBufLen
);
908 if (pAdapterInfo
== NULL
)
913 dwRetVal
= GetAdaptersInfo( pAdapterInfo
, &ulOutBufLen
);
915 if (dwRetVal
!= NO_ERROR
)
920 pAdapter
= pAdapterInfo
;
923 if (strcmp(pAdapter
->AdapterName
, nameStr
) == 0)
925 ifIndex
= pAdapter
->Index
;
929 pAdapter
= pAdapter
->Next
;
934 if (pAdapterInfo
!= NULL
)
936 free( pAdapterInfo
);