2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
27 $Log: JNISupport.c,v $
28 Revision 1.2 2004/05/28 23:34:42 ksekar
29 <rdar://problem/3672903>: Java project doesn't build on Tiger8A132
31 Revision 1.1 2004/04/30 16:29:35 rpantos
35 This file contains the platform support for DNSSD and related Java classes.
36 It is used to shim through to the underlying <dns_sd.h> API.
39 - normalize code to eliminate USE_WIN_API
42 // AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
43 // callbacks automatically (as it does on Windows).
44 // AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
45 // invoke response callbacks (as is true on Mac OS X).
46 #ifndef AUTO_CALLBACKS
47 #define AUTO_CALLBACKS 0
50 // (Temporary, I hope - RNP)
51 // USE_WIN_API should be set to 1 to use the DNSSD.h API (on Windows).
52 // USE_WIN_API should be set to 0 to use the dns_sd.h API (on everything else).
69 #define CALLBACK_COMPAT
73 #include <sys/types.h>
74 #include <sys/select.h>
77 #include "DNSSD.java.h"
79 // convenience definition
81 #define _UNUSED __attribute__ ((unused))
87 kInterfaceVersion
= 1 // Must match version in .jar file
90 typedef struct OpContext OpContext
;
94 DNSServiceRef ServiceRef
;
102 // For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
104 JavaVM
*gJavaVM
= NULL
;
108 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv
*pEnv
, jclass cls
,
111 /* Ensure that caller & interface versions match. */
112 if ( callerVersion
!= kInterfaceVersion
)
113 return kDNSServiceErr_Incompatible
;
117 DNSServiceErrorType err
;
119 err
= DNSServiceInitialize( kDNSServiceInitializeFlagsNone
, 0);
120 if ( err
!= kDNSServiceErr_NoError
)
129 if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM
, 1, &numVMs
))
130 return kDNSServiceErr_BadState
;
134 // Set AppleDNSSD.hasAutoCallbacks
137 jboolean hasAutoC
= JNI_TRUE
;
139 jboolean hasAutoC
= JNI_FALSE
;
141 jfieldID hasAutoCField
= (*pEnv
)->GetStaticFieldID( pEnv
, cls
, "hasAutoCallbacks", "Z");
142 (*pEnv
)->SetStaticBooleanField( pEnv
, cls
, hasAutoCField
, hasAutoC
);
145 return kDNSServiceErr_NoError
;
149 static const char* SafeGetUTFChars( JNIEnv
*pEnv
, jstring str
)
150 // Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
152 return str
!= NULL
? (*pEnv
)->GetStringUTFChars( pEnv
, str
, 0) : NULL
;
155 static void SafeReleaseUTFChars( JNIEnv
*pEnv
, jstring str
, const char *buff
)
156 // Wrapper for JNI GetStringUTFChars() that handles null str.
159 (*pEnv
)->ReleaseStringUTFChars( pEnv
, str
, buff
);
164 static void SetupCallbackState( JNIEnv
**ppEnv
)
166 (*gJavaVM
)->AttachCurrentThread( gJavaVM
, (void**) ppEnv
, NULL
);
169 static void TeardownCallbackState( void )
171 (*gJavaVM
)->DetachCurrentThread( gJavaVM
);
174 #else // AUTO_CALLBACKS
176 static void SetupCallbackState( JNIEnv
**ppEnv _UNUSED
)
178 // No setup necessary if ProcessResults() has been called
181 static void TeardownCallbackState( void )
183 // No teardown necessary if ProcessResults() has been called
185 #endif // AUTO_CALLBACKS
188 static OpContext
*NewContext( JNIEnv
*pEnv
, jobject owner
, const char *ownerClass
,
189 const char *callbackName
, const char *callbackSig
)
190 // Create and initialize a new OpContext.
192 OpContext
*pContext
= (OpContext
*) malloc( sizeof *pContext
);;
194 if ( pContext
!= NULL
)
196 jfieldID clientField
= (*pEnv
)->GetFieldID( pEnv
, (*pEnv
)->GetObjectClass( pEnv
, owner
),
197 "fClient", ownerClass
);
199 pContext
->JavaObj
= (*pEnv
)->NewWeakGlobalRef( pEnv
, owner
); // must convert local ref to global to cache;
200 pContext
->ClientObj
= (*pEnv
)->GetObjectField( pEnv
, owner
, clientField
);
201 pContext
->ClientObj
= (*pEnv
)->NewWeakGlobalRef( pEnv
, pContext
->ClientObj
); // must convert local ref to global to cache
202 pContext
->Callback
= (*pEnv
)->GetMethodID( pEnv
,
203 (*pEnv
)->GetObjectClass( pEnv
, pContext
->ClientObj
),
204 callbackName
, callbackSig
);
205 pContext
->Callback2
= NULL
; // not always used
212 static void ReportError( JNIEnv
*pEnv
, jobject target
, jobject service
, DNSServiceErrorType err
)
213 // Invoke operationFailed() method on target with err.
215 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, target
);
216 jmethodID opFailed
= (*pEnv
)->GetMethodID( pEnv
, cls
, "operationFailed",
217 "(Lcom/apple/dnssd/DNSSDService;I)V");
219 (*pEnv
)->CallVoidMethod( pEnv
, target
, opFailed
, service
, err
);
222 JNIEXPORT
void JNICALL
Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv
*pEnv
, jobject pThis
)
223 /* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
225 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
226 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
228 if ( contextField
!= 0)
230 OpContext
*pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
231 if ( pContext
!= NULL
)
233 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, 0);
234 if ( pContext
->ServiceRef
!= NULL
)
235 DNSServiceRefDeallocate( pContext
->ServiceRef
);
237 (*pEnv
)->DeleteWeakGlobalRef( pEnv
, pContext
->JavaObj
);
238 (*pEnv
)->DeleteWeakGlobalRef( pEnv
, pContext
->ClientObj
);
245 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv
*pEnv
, jobject pThis
, jint msTimeout
)
246 /* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */
249 return -1; // BlockForData() not supported with AUTO_CALLBACKS
250 #else // AUTO_CALLBACKS
251 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
252 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
255 if ( contextField
!= 0)
257 OpContext
*pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
258 if ( pContext
!= NULL
)
261 int sd
= DNSServiceRefSockFD( pContext
->ServiceRef
);
262 struct timeval timeout
= { msTimeout
/ 1000, 10 * (msTimeout
% 1000) };
263 struct timeval
*pTimeout
= msTimeout
== -1 ? NULL
: &timeout
;
266 FD_SET( sd
, &readFDs
);
268 rc
= select( sd
+ 1, &readFDs
, (fd_set
*) NULL
, (fd_set
*) NULL
, pTimeout
);
273 #endif // AUTO_CALLBACKS
277 JNIEXPORT
void JNICALL
Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv
*pEnv
, jobject pThis
)
278 /* Call through to DNSServiceProcessResult() while data remains on socket. */
280 #if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
282 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
283 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
284 OpContext
*pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
286 if ( pContext
!= NULL
)
288 int sd
= DNSServiceRefSockFD( pContext
->ServiceRef
);
290 struct timeval zeroTimeout
= { 0, 0 };
292 pContext
->Env
= pEnv
;
295 FD_SET( sd
, &readFDs
);
297 while ( 0 < select( sd
+ 1, &readFDs
, (fd_set
*) NULL
, (fd_set
*) NULL
, &zeroTimeout
))
299 DNSServiceProcessResult( pContext
->ServiceRef
);
302 #endif // AUTO_CALLBACKS
306 static void CALLBACK_COMPAT
ServiceBrowseReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
307 DNSServiceErrorType errorCode
, const char *serviceName
, const char *regtype
,
308 const char *replyDomain
, void *context
)
310 OpContext
*pContext
= (OpContext
*) context
;
312 SetupCallbackState( &pContext
->Env
);
314 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
)
316 if ( errorCode
== kDNSServiceErr_NoError
)
318 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
,
319 ( flags
& kDNSServiceFlagsAdd
) != 0 ? pContext
->Callback
: pContext
->Callback2
,
320 pContext
->JavaObj
, flags
, interfaceIndex
,
321 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, serviceName
),
322 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, regtype
),
323 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, replyDomain
));
326 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
329 TeardownCallbackState();
332 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv
*pEnv
, jobject pThis
,
333 jint flags
, jint ifIndex
, jstring regType
, jstring domain
)
335 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
336 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
337 OpContext
*pContext
= NULL
;
338 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
340 if ( contextField
!= 0)
341 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/BrowseListener;", "serviceFound",
342 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
344 err
= kDNSServiceErr_BadParam
;
346 if ( pContext
!= NULL
)
348 const char *regStr
= SafeGetUTFChars( pEnv
, regType
);
349 const char *domainStr
= SafeGetUTFChars( pEnv
, domain
);
351 pContext
->Callback2
= (*pEnv
)->GetMethodID( pEnv
,
352 (*pEnv
)->GetObjectClass( pEnv
, pContext
->ClientObj
),
353 "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
355 err
= DNSServiceBrowse( &pContext
->ServiceRef
, flags
, ifIndex
, regStr
, domainStr
, ServiceBrowseReply
, pContext
);
356 if ( err
== kDNSServiceErr_NoError
)
358 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
361 SafeReleaseUTFChars( pEnv
, regType
, regStr
);
362 SafeReleaseUTFChars( pEnv
, domain
, domainStr
);
365 err
= kDNSServiceErr_NoMemory
;
371 static void CALLBACK_COMPAT
ServiceResolveReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
372 DNSServiceErrorType errorCode
, const char *fullname
, const char *hosttarget
,
373 uint16_t port
, uint16_t txtLen
, const char *txtRecord
, void *context
)
375 OpContext
*pContext
= (OpContext
*) context
;
382 SetupCallbackState( &pContext
->Env
);
384 txtCls
= (*pContext
->Env
)->FindClass( pContext
->Env
, "com/apple/dnssd/TXTRecord");
385 txtCtor
= (*pContext
->Env
)->GetMethodID( pContext
->Env
, txtCls
, "<init>", "([B)V");
387 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
&& txtCtor
!= NULL
&&
388 NULL
!= ( txtBytes
= (*pContext
->Env
)->NewByteArray( pContext
->Env
, txtLen
)))
390 if ( errorCode
== kDNSServiceErr_NoError
)
392 // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
393 // pattern into a number here.
394 port
= ( ((unsigned char*) &port
)[0] << 8) | ((unsigned char*) &port
)[1];
396 // Initialize txtBytes with contents of txtRecord
397 pBytes
= (*pContext
->Env
)->GetByteArrayElements( pContext
->Env
, txtBytes
, NULL
);
398 memcpy( pBytes
, txtRecord
, txtLen
);
399 (*pContext
->Env
)->ReleaseByteArrayElements( pContext
->Env
, txtBytes
, pBytes
, JNI_COMMIT
);
401 // Construct txtObj with txtBytes
402 txtObj
= (*pContext
->Env
)->NewObject( pContext
->Env
, txtCls
, txtCtor
, txtBytes
);
403 (*pContext
->Env
)->DeleteLocalRef( pContext
->Env
, txtBytes
);
405 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
, pContext
->Callback
,
406 pContext
->JavaObj
, flags
, interfaceIndex
,
407 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, fullname
),
408 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, hosttarget
),
412 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
415 TeardownCallbackState();
418 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv
*pEnv
, jobject pThis
,
419 jint flags
, jint ifIndex
, jstring serviceName
, jstring regType
, jstring domain
)
421 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
422 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
423 OpContext
*pContext
= NULL
;
424 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
426 if ( contextField
!= 0)
427 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/ResolveListener;", "serviceResolved",
428 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
430 err
= kDNSServiceErr_BadParam
;
432 if ( pContext
!= NULL
)
434 const char *servStr
= SafeGetUTFChars( pEnv
, serviceName
);
435 const char *regStr
= SafeGetUTFChars( pEnv
, regType
);
436 const char *domainStr
= SafeGetUTFChars( pEnv
, domain
);
438 err
= DNSServiceResolve( &pContext
->ServiceRef
, flags
, ifIndex
,
439 servStr
, regStr
, domainStr
, ServiceResolveReply
, pContext
);
440 if ( err
== kDNSServiceErr_NoError
)
442 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
445 SafeReleaseUTFChars( pEnv
, serviceName
, servStr
);
446 SafeReleaseUTFChars( pEnv
, regType
, regStr
);
447 SafeReleaseUTFChars( pEnv
, domain
, domainStr
);
450 err
= kDNSServiceErr_NoMemory
;
456 static void CALLBACK_COMPAT
ServiceRegisterReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
,
457 DNSServiceErrorType errorCode
, const char *fullname
,
458 const char *regType
, const char *domain
, void *context
)
460 OpContext
*pContext
= (OpContext
*) context
;
462 SetupCallbackState( &pContext
->Env
);
464 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
)
466 if ( errorCode
== kDNSServiceErr_NoError
)
468 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
, pContext
->Callback
,
469 pContext
->JavaObj
, flags
,
470 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, fullname
),
471 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, regType
),
472 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, domain
));
475 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
477 TeardownCallbackState();
480 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv
*pEnv
, jobject pThis
,
481 jint ifIndex
, jint flags
, jstring serviceName
, jstring regType
,
482 jstring domain
, jstring host
, jint port
, jbyteArray txtRecord
)
484 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
485 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
486 OpContext
*pContext
= NULL
;
487 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
491 if ( contextField
!= 0)
492 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/RegisterListener;", "serviceRegistered",
493 "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
495 err
= kDNSServiceErr_BadParam
;
497 if ( pContext
!= NULL
)
499 const char *servStr
= SafeGetUTFChars( pEnv
, serviceName
);
500 const char *regStr
= SafeGetUTFChars( pEnv
, regType
);
501 const char *domainStr
= SafeGetUTFChars( pEnv
, domain
);
502 const char *hostStr
= SafeGetUTFChars( pEnv
, host
);
504 // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
505 // big-endian number into a 16-bit pattern here.
506 uint16_t portBits
= port
;
507 portBits
= ( ((unsigned char*) &portBits
)[0] << 8) | ((unsigned char*) &portBits
)[1];
509 pBytes
= txtRecord
? (*pEnv
)->GetByteArrayElements( pEnv
, txtRecord
, NULL
) : NULL
;
510 numBytes
= txtRecord
? (*pEnv
)->GetArrayLength( pEnv
, txtRecord
) : 0;
512 err
= DNSServiceRegister( &pContext
->ServiceRef
, flags
, ifIndex
, servStr
, regStr
,
513 domainStr
, hostStr
, portBits
,
514 numBytes
, pBytes
, ServiceRegisterReply
, pContext
);
515 if ( err
== kDNSServiceErr_NoError
)
517 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
521 (*pEnv
)->ReleaseByteArrayElements( pEnv
, txtRecord
, pBytes
, 0);
523 SafeReleaseUTFChars( pEnv
, serviceName
, servStr
);
524 SafeReleaseUTFChars( pEnv
, regType
, regStr
);
525 SafeReleaseUTFChars( pEnv
, domain
, domainStr
);
526 SafeReleaseUTFChars( pEnv
, host
, hostStr
);
529 err
= kDNSServiceErr_NoMemory
;
534 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv
*pEnv
, jobject pThis
,
535 jint flags
, jint rrType
, jbyteArray rData
, jint ttl
, jobject destObj
)
537 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
538 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
539 jclass destCls
= (*pEnv
)->GetObjectClass( pEnv
, destObj
);
540 jfieldID recField
= (*pEnv
)->GetFieldID( pEnv
, destCls
, "fRecord", "I");
541 OpContext
*pContext
= NULL
;
542 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
547 if ( contextField
!= 0)
548 pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
549 if ( pContext
== NULL
|| pContext
->ServiceRef
== NULL
)
550 return kDNSServiceErr_BadParam
;
552 pBytes
= (*pEnv
)->GetByteArrayElements( pEnv
, rData
, NULL
);
553 numBytes
= (*pEnv
)->GetArrayLength( pEnv
, rData
);
555 err
= DNSServiceAddRecord( pContext
->ServiceRef
, &recRef
, flags
, rrType
, numBytes
, pBytes
, ttl
);
556 if ( err
== kDNSServiceErr_NoError
)
558 (*pEnv
)->SetIntField( pEnv
, destObj
, recField
, (jint
) recRef
);
562 (*pEnv
)->ReleaseByteArrayElements( pEnv
, rData
, pBytes
, 0);
567 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleRegistration_UpdateRecord( JNIEnv
*pEnv
, jobject pThis
,
568 jobject destObj
, jint flags
, jbyteArray rData
, jint ttl
)
570 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
571 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
572 jclass destCls
= (*pEnv
)->GetObjectClass( pEnv
, destObj
);
573 jfieldID recField
= (*pEnv
)->GetFieldID( pEnv
, destCls
, "fRecord", "I");
574 OpContext
*pContext
= NULL
;
575 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
578 DNSRecordRef recRef
= NULL
;
580 if ( contextField
!= 0)
581 pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
583 recRef
= (DNSRecordRef
) (*pEnv
)->GetIntField( pEnv
, destObj
, recField
);
584 if ( pContext
== NULL
|| pContext
->ServiceRef
== NULL
)
585 return kDNSServiceErr_BadParam
;
587 pBytes
= (*pEnv
)->GetByteArrayElements( pEnv
, rData
, NULL
);
588 numBytes
= (*pEnv
)->GetArrayLength( pEnv
, rData
);
590 err
= DNSServiceUpdateRecord( pContext
->ServiceRef
, recRef
, flags
, numBytes
, pBytes
, ttl
);
593 (*pEnv
)->ReleaseByteArrayElements( pEnv
, rData
, pBytes
, 0);
598 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleRegistration_RemoveRecord( JNIEnv
*pEnv
, jobject pThis
,
599 jobject destObj
, jint flags
)
601 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
602 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
603 jclass destCls
= (*pEnv
)->GetObjectClass( pEnv
, destObj
);
604 jfieldID recField
= (*pEnv
)->GetFieldID( pEnv
, destCls
, "fRecord", "I");
605 OpContext
*pContext
= NULL
;
606 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
607 DNSRecordRef recRef
= NULL
;
609 if ( contextField
!= 0)
610 pContext
= (OpContext
*) (*pEnv
)->GetIntField( pEnv
, pThis
, contextField
);
612 recRef
= (DNSRecordRef
) (*pEnv
)->GetIntField( pEnv
, destObj
, recField
);
613 if ( pContext
== NULL
|| pContext
->ServiceRef
== NULL
)
614 return kDNSServiceErr_BadParam
;
616 err
= DNSServiceRemoveRecord( pContext
->ServiceRef
, recRef
, flags
);
622 static void CALLBACK_COMPAT
ServiceQueryReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
623 DNSServiceErrorType errorCode
, const char *serviceName
,
624 uint16_t rrtype
, uint16_t rrclass
, uint16_t rdlen
,
625 const void *rdata
, uint32_t ttl
, void *context
)
627 OpContext
*pContext
= (OpContext
*) context
;
631 SetupCallbackState( &pContext
->Env
);
633 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
&&
634 NULL
!= ( rDataObj
= (*pContext
->Env
)->NewByteArray( pContext
->Env
, rdlen
)))
636 if ( errorCode
== kDNSServiceErr_NoError
)
638 // Initialize rDataObj with contents of rdata
639 pBytes
= (*pContext
->Env
)->GetByteArrayElements( pContext
->Env
, rDataObj
, NULL
);
640 memcpy( pBytes
, rdata
, rdlen
);
641 (*pContext
->Env
)->ReleaseByteArrayElements( pContext
->Env
, rDataObj
, pBytes
, JNI_COMMIT
);
643 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
, pContext
->Callback
,
644 pContext
->JavaObj
, flags
, interfaceIndex
,
645 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, serviceName
),
646 rrtype
, rrclass
, rDataObj
, ttl
);
649 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
651 TeardownCallbackState();
654 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv
*pEnv
, jobject pThis
,
655 jint flags
, jint ifIndex
, jstring serviceName
, jint rrtype
, jint rrclass
)
657 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
658 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
659 OpContext
*pContext
= NULL
;
660 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
662 if ( contextField
!= 0)
663 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/QueryListener;", "queryAnswered",
664 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
666 err
= kDNSServiceErr_BadParam
;
668 if ( pContext
!= NULL
)
670 const char *servStr
= SafeGetUTFChars( pEnv
, serviceName
);
672 err
= DNSServiceQueryRecord( &pContext
->ServiceRef
, flags
, ifIndex
, servStr
,
673 rrtype
, rrclass
, ServiceQueryReply
, pContext
);
674 if ( err
== kDNSServiceErr_NoError
)
676 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
679 SafeReleaseUTFChars( pEnv
, serviceName
, servStr
);
682 err
= kDNSServiceErr_NoMemory
;
688 static void CALLBACK_COMPAT
DomainEnumReply( DNSServiceRef sdRef _UNUSED
, DNSServiceFlags flags
, uint32_t interfaceIndex
,
689 DNSServiceErrorType errorCode
, const char *replyDomain
, void *context
)
691 OpContext
*pContext
= (OpContext
*) context
;
693 SetupCallbackState( &pContext
->Env
);
695 if ( pContext
->ClientObj
!= NULL
&& pContext
->Callback
!= NULL
)
697 if ( errorCode
== kDNSServiceErr_NoError
)
699 (*pContext
->Env
)->CallVoidMethod( pContext
->Env
, pContext
->ClientObj
,
700 ( flags
& kDNSServiceFlagsAdd
) != 0 ? pContext
->Callback
: pContext
->Callback2
,
701 pContext
->JavaObj
, flags
, interfaceIndex
,
702 (*pContext
->Env
)->NewStringUTF( pContext
->Env
, replyDomain
));
705 ReportError( pContext
->Env
, pContext
->ClientObj
, pContext
->JavaObj
, errorCode
);
707 TeardownCallbackState();
710 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv
*pEnv
, jobject pThis
,
711 jint flags
, jint ifIndex
)
713 jclass cls
= (*pEnv
)->GetObjectClass( pEnv
, pThis
);
714 jfieldID contextField
= (*pEnv
)->GetFieldID( pEnv
, cls
, "fNativeContext", "I");
715 OpContext
*pContext
= NULL
;
716 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
718 if ( contextField
!= 0)
719 pContext
= NewContext( pEnv
, pThis
, "Lcom/apple/dnssd/DomainListener;", "domainFound",
720 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
722 err
= kDNSServiceErr_BadParam
;
724 if ( pContext
!= NULL
)
726 pContext
->Callback2
= (*pEnv
)->GetMethodID( pEnv
,
727 (*pEnv
)->GetObjectClass( pEnv
, pContext
->ClientObj
),
728 "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
730 err
= DNSServiceEnumerateDomains( &pContext
->ServiceRef
, flags
, ifIndex
,
731 DomainEnumReply
, pContext
);
732 if ( err
== kDNSServiceErr_NoError
)
734 (*pEnv
)->SetIntField( pEnv
, pThis
, contextField
, (jint
) pContext
);
738 err
= kDNSServiceErr_NoMemory
;
744 JNIEXPORT jint JNICALL
Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv
*pEnv
, jobject pThis _UNUSED
,
745 jstring serviceName
, jstring regtype
, jstring domain
, jobjectArray pOut
)
747 DNSServiceErrorType err
= kDNSServiceErr_NoError
;
748 const char *nameStr
= SafeGetUTFChars( pEnv
, serviceName
);
749 const char *regStr
= SafeGetUTFChars( pEnv
, regtype
);
750 const char *domStr
= SafeGetUTFChars( pEnv
, domain
);
751 char buff
[ kDNSServiceMaxDomainName
+ 1];
753 err
= DNSServiceConstructFullName( buff
, nameStr
, regStr
, domStr
);
755 if ( err
== kDNSServiceErr_NoError
)
757 // pOut is expected to be a String[1] array.
758 (*pEnv
)->SetObjectArrayElement( pEnv
, pOut
, 0, (*pEnv
)->NewStringUTF( pEnv
, buff
));
761 SafeReleaseUTFChars( pEnv
, serviceName
, nameStr
);
762 SafeReleaseUTFChars( pEnv
, regtype
, regStr
);
763 SafeReleaseUTFChars( pEnv
, domain
, domStr
);
768 JNIEXPORT
void JNICALL
Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv
*pEnv
, jobject pThis _UNUSED
,
769 jint flags
, jint ifIndex
, jstring fullName
,
770 jint rrtype
, jint rrclass
, jbyteArray rdata
)
774 const char *nameStr
= SafeGetUTFChars( pEnv
, fullName
);
776 pBytes
= (*pEnv
)->GetByteArrayElements( pEnv
, rdata
, NULL
);
777 numBytes
= (*pEnv
)->GetArrayLength( pEnv
, rdata
);
779 DNSServiceReconfirmRecord( flags
, ifIndex
, nameStr
, rrtype
, rrclass
, numBytes
, pBytes
);
782 (*pEnv
)->ReleaseByteArrayElements( pEnv
, rdata
, pBytes
, 0);
784 SafeReleaseUTFChars( pEnv
, fullName
, nameStr
);