]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/Java/JNISupport.c
mDNSResponder-66.3.tar.gz
[apple/mdnsresponder.git] / mDNSShared / Java / JNISupport.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
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
30
31 Revision 1.1 2004/04/30 16:29:35 rpantos
32 First checked in.
33
34
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.
37
38 To do:
39 - normalize code to eliminate USE_WIN_API
40 */
41
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
48 #endif
49
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).
53 #ifndef USE_WIN_API
54 #define USE_WIN_API 0
55 #endif
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <jni.h>
61
62 #if USE_WIN_API
63 #include <DNSSD.h>
64 #else
65 #include <dns_sd.h>
66 #endif
67
68 #if !USE_WIN_API
69 #define CALLBACK_COMPAT
70 #endif
71
72 #if !AUTO_CALLBACKS
73 #include <sys/types.h>
74 #include <sys/select.h>
75 #endif
76
77 #include "DNSSD.java.h"
78
79 // convenience definition
80 #ifdef __GNUC__
81 #define _UNUSED __attribute__ ((unused))
82 #else
83 #define _UNUSED
84 #endif
85
86 enum {
87 kInterfaceVersion = 1 // Must match version in .jar file
88 };
89
90 typedef struct OpContext OpContext;
91
92 struct OpContext
93 {
94 DNSServiceRef ServiceRef;
95 JNIEnv *Env;
96 jobject JavaObj;
97 jobject ClientObj;
98 jmethodID Callback;
99 jmethodID Callback2;
100 };
101
102 // For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
103 #if AUTO_CALLBACKS
104 JavaVM *gJavaVM = NULL;
105 #endif
106
107
108 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
109 jint callerVersion)
110 {
111 /* Ensure that caller & interface versions match. */
112 if ( callerVersion != kInterfaceVersion)
113 return kDNSServiceErr_Incompatible;
114
115 #if USE_WIN_API
116 {
117 DNSServiceErrorType err;
118
119 err = DNSServiceInitialize( kDNSServiceInitializeFlagsNone, 0);
120 if ( err != kDNSServiceErr_NoError)
121 return err;
122 }
123 #endif
124
125 #if AUTO_CALLBACKS
126 {
127 jsize numVMs;
128
129 if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
130 return kDNSServiceErr_BadState;
131 }
132 #endif
133
134 // Set AppleDNSSD.hasAutoCallbacks
135 {
136 #if AUTO_CALLBACKS
137 jboolean hasAutoC = JNI_TRUE;
138 #else
139 jboolean hasAutoC = JNI_FALSE;
140 #endif
141 jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
142 (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
143 }
144
145 return kDNSServiceErr_NoError;
146 }
147
148
149 static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str)
150 // Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
151 {
152 return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
153 }
154
155 static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
156 // Wrapper for JNI GetStringUTFChars() that handles null str.
157 {
158 if ( str != NULL)
159 (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
160 }
161
162
163 #if AUTO_CALLBACKS
164 static void SetupCallbackState( JNIEnv **ppEnv)
165 {
166 (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
167 }
168
169 static void TeardownCallbackState( void )
170 {
171 (*gJavaVM)->DetachCurrentThread( gJavaVM);
172 }
173
174 #else // AUTO_CALLBACKS
175
176 static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
177 {
178 // No setup necessary if ProcessResults() has been called
179 }
180
181 static void TeardownCallbackState( void )
182 {
183 // No teardown necessary if ProcessResults() has been called
184 }
185 #endif // AUTO_CALLBACKS
186
187
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.
191 {
192 OpContext *pContext = (OpContext*) malloc( sizeof *pContext);;
193
194 if ( pContext != NULL)
195 {
196 jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
197 "fClient", ownerClass);
198
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
206 }
207
208 return pContext;
209 }
210
211
212 static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
213 // Invoke operationFailed() method on target with err.
214 {
215 jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
216 jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
217 "(Lcom/apple/dnssd/DNSSDService;I)V");
218
219 (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
220 }
221
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. */
224 {
225 jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
226 jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
227
228 if ( contextField != 0)
229 {
230 OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
231 if ( pContext != NULL)
232 {
233 (*pEnv)->SetIntField( pEnv, pThis, contextField, 0);
234 if ( pContext->ServiceRef != NULL)
235 DNSServiceRefDeallocate( pContext->ServiceRef);
236
237 (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
238 (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
239 free( pContext);
240 }
241 }
242 }
243
244
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. */
247 {
248 #if AUTO_CALLBACKS
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");
253 jint rc = -1;
254
255 if ( contextField != 0)
256 {
257 OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
258 if ( pContext != NULL)
259 {
260 fd_set readFDs;
261 int sd = DNSServiceRefSockFD( pContext->ServiceRef);
262 struct timeval timeout = { msTimeout / 1000, 10 * (msTimeout % 1000) };
263 struct timeval *pTimeout = msTimeout == -1 ? NULL : &timeout;
264
265 FD_ZERO( &readFDs);
266 FD_SET( sd, &readFDs);
267
268 rc = select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, pTimeout);
269 }
270 }
271
272 return rc;
273 #endif // AUTO_CALLBACKS
274 }
275
276
277 JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
278 /* Call through to DNSServiceProcessResult() while data remains on socket. */
279 {
280 #if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
281
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);
285
286 if ( pContext != NULL)
287 {
288 int sd = DNSServiceRefSockFD( pContext->ServiceRef);
289 fd_set readFDs;
290 struct timeval zeroTimeout = { 0, 0 };
291
292 pContext->Env = pEnv;
293
294 FD_ZERO( &readFDs);
295 FD_SET( sd, &readFDs);
296
297 while ( 0 < select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
298 {
299 DNSServiceProcessResult( pContext->ServiceRef);
300 }
301 }
302 #endif // AUTO_CALLBACKS
303 }
304
305
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)
309 {
310 OpContext *pContext = (OpContext*) context;
311
312 SetupCallbackState( &pContext->Env);
313
314 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
315 {
316 if ( errorCode == kDNSServiceErr_NoError)
317 {
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));
324 }
325 else
326 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
327 }
328
329 TeardownCallbackState();
330 }
331
332 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
333 jint flags, jint ifIndex, jstring regType, jstring domain)
334 {
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;
339
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");
343 else
344 err = kDNSServiceErr_BadParam;
345
346 if ( pContext != NULL)
347 {
348 const char *regStr = SafeGetUTFChars( pEnv, regType);
349 const char *domainStr = SafeGetUTFChars( pEnv, domain);
350
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");
354
355 err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
356 if ( err == kDNSServiceErr_NoError)
357 {
358 (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
359 }
360
361 SafeReleaseUTFChars( pEnv, regType, regStr);
362 SafeReleaseUTFChars( pEnv, domain, domainStr);
363 }
364 else
365 err = kDNSServiceErr_NoMemory;
366
367 return err;
368 }
369
370
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)
374 {
375 OpContext *pContext = (OpContext*) context;
376 jclass txtCls;
377 jmethodID txtCtor;
378 jbyteArray txtBytes;
379 jobject txtObj;
380 jbyte *pBytes;
381
382 SetupCallbackState( &pContext->Env);
383
384 txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
385 txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
386
387 if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
388 NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
389 {
390 if ( errorCode == kDNSServiceErr_NoError)
391 {
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];
395
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);
400
401 // Construct txtObj with txtBytes
402 txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
403 (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
404
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),
409 port, txtObj);
410 }
411 else
412 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
413 }
414
415 TeardownCallbackState();
416 }
417
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)
420 {
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;
425
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");
429 else
430 err = kDNSServiceErr_BadParam;
431
432 if ( pContext != NULL)
433 {
434 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
435 const char *regStr = SafeGetUTFChars( pEnv, regType);
436 const char *domainStr = SafeGetUTFChars( pEnv, domain);
437
438 err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
439 servStr, regStr, domainStr, ServiceResolveReply, pContext);
440 if ( err == kDNSServiceErr_NoError)
441 {
442 (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
443 }
444
445 SafeReleaseUTFChars( pEnv, serviceName, servStr);
446 SafeReleaseUTFChars( pEnv, regType, regStr);
447 SafeReleaseUTFChars( pEnv, domain, domainStr);
448 }
449 else
450 err = kDNSServiceErr_NoMemory;
451
452 return err;
453 }
454
455
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)
459 {
460 OpContext *pContext = (OpContext*) context;
461
462 SetupCallbackState( &pContext->Env);
463
464 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
465 {
466 if ( errorCode == kDNSServiceErr_NoError)
467 {
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));
473 }
474 else
475 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
476 }
477 TeardownCallbackState();
478 }
479
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)
483 {
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;
488 jbyte *pBytes;
489 jsize numBytes;
490
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");
494 else
495 err = kDNSServiceErr_BadParam;
496
497 if ( pContext != NULL)
498 {
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);
503
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];
508
509 pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
510 numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
511
512 err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
513 domainStr, hostStr, portBits,
514 numBytes, pBytes, ServiceRegisterReply, pContext);
515 if ( err == kDNSServiceErr_NoError)
516 {
517 (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
518 }
519
520 if ( pBytes != NULL)
521 (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
522
523 SafeReleaseUTFChars( pEnv, serviceName, servStr);
524 SafeReleaseUTFChars( pEnv, regType, regStr);
525 SafeReleaseUTFChars( pEnv, domain, domainStr);
526 SafeReleaseUTFChars( pEnv, host, hostStr);
527 }
528 else
529 err = kDNSServiceErr_NoMemory;
530
531 return err;
532 }
533
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)
536 {
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;
543 jbyte *pBytes;
544 jsize numBytes;
545 DNSRecordRef recRef;
546
547 if ( contextField != 0)
548 pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
549 if ( pContext == NULL || pContext->ServiceRef == NULL)
550 return kDNSServiceErr_BadParam;
551
552 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
553 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
554
555 err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
556 if ( err == kDNSServiceErr_NoError)
557 {
558 (*pEnv)->SetIntField( pEnv, destObj, recField, (jint) recRef);
559 }
560
561 if ( pBytes != NULL)
562 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
563
564 return err;
565 }
566
567 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_UpdateRecord( JNIEnv *pEnv, jobject pThis,
568 jobject destObj, jint flags, jbyteArray rData, jint ttl)
569 {
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;
576 jbyte *pBytes;
577 jsize numBytes;
578 DNSRecordRef recRef = NULL;
579
580 if ( contextField != 0)
581 pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
582 if ( recField != 0)
583 recRef = (DNSRecordRef) (*pEnv)->GetIntField( pEnv, destObj, recField);
584 if ( pContext == NULL || pContext->ServiceRef == NULL)
585 return kDNSServiceErr_BadParam;
586
587 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
588 numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
589
590 err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
591
592 if ( pBytes != NULL)
593 (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
594
595 return err;
596 }
597
598 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_RemoveRecord( JNIEnv *pEnv, jobject pThis,
599 jobject destObj, jint flags)
600 {
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;
608
609 if ( contextField != 0)
610 pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
611 if ( recField != 0)
612 recRef = (DNSRecordRef) (*pEnv)->GetIntField( pEnv, destObj, recField);
613 if ( pContext == NULL || pContext->ServiceRef == NULL)
614 return kDNSServiceErr_BadParam;
615
616 err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, flags);
617
618 return err;
619 }
620
621
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)
626 {
627 OpContext *pContext = (OpContext*) context;
628 jbyteArray rDataObj;
629 jbyte *pBytes;
630
631 SetupCallbackState( &pContext->Env);
632
633 if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
634 NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
635 {
636 if ( errorCode == kDNSServiceErr_NoError)
637 {
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);
642
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);
647 }
648 else
649 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
650 }
651 TeardownCallbackState();
652 }
653
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)
656 {
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;
661
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");
665 else
666 err = kDNSServiceErr_BadParam;
667
668 if ( pContext != NULL)
669 {
670 const char *servStr = SafeGetUTFChars( pEnv, serviceName);
671
672 err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
673 rrtype, rrclass, ServiceQueryReply, pContext);
674 if ( err == kDNSServiceErr_NoError)
675 {
676 (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
677 }
678
679 SafeReleaseUTFChars( pEnv, serviceName, servStr);
680 }
681 else
682 err = kDNSServiceErr_NoMemory;
683
684 return err;
685 }
686
687
688 static void CALLBACK_COMPAT DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
689 DNSServiceErrorType errorCode, const char *replyDomain, void *context)
690 {
691 OpContext *pContext = (OpContext*) context;
692
693 SetupCallbackState( &pContext->Env);
694
695 if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
696 {
697 if ( errorCode == kDNSServiceErr_NoError)
698 {
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));
703 }
704 else
705 ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
706 }
707 TeardownCallbackState();
708 }
709
710 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
711 jint flags, jint ifIndex)
712 {
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;
717
718 if ( contextField != 0)
719 pContext = NewContext( pEnv, pThis, "Lcom/apple/dnssd/DomainListener;", "domainFound",
720 "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
721 else
722 err = kDNSServiceErr_BadParam;
723
724 if ( pContext != NULL)
725 {
726 pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
727 (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
728 "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
729
730 err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
731 DomainEnumReply, pContext);
732 if ( err == kDNSServiceErr_NoError)
733 {
734 (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
735 }
736 }
737 else
738 err = kDNSServiceErr_NoMemory;
739
740 return err;
741 }
742
743
744 JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
745 jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
746 {
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];
752
753 err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
754
755 if ( err == kDNSServiceErr_NoError)
756 {
757 // pOut is expected to be a String[1] array.
758 (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
759 }
760
761 SafeReleaseUTFChars( pEnv, serviceName, nameStr);
762 SafeReleaseUTFChars( pEnv, regtype, regStr);
763 SafeReleaseUTFChars( pEnv, domain, domStr);
764
765 return err;
766 }
767
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)
771 {
772 jbyte *pBytes;
773 jsize numBytes;
774 const char *nameStr = SafeGetUTFChars( pEnv, fullName);
775
776 pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
777 numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
778
779 DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
780
781 if ( pBytes != NULL)
782 (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
783
784 SafeReleaseUTFChars( pEnv, fullName, nameStr);
785 }
786
787
788