#ifndef AUTO_CALLBACKS
#define AUTO_CALLBACKS 0
#endif
#if !AUTO_CALLBACKS
#ifdef _WIN32
#include <winsock2.h>
#else //_WIN32
#include <sys/types.h>
#include <sys/select.h>
#endif // _WIN32
#endif // AUTO_CALLBACKS
#include <dns_sd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#include <iphlpapi.h>
static char * if_indextoname( DWORD ifIndex, char * nameBuff);
static DWORD if_nametoindex( const char * nameStr );
#define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
#else // _WIN32
#include <sys/socket.h>
#include <net/if.h>
#endif // _WIN32
#include <jni.h>
#include "DNSSD.java.h"
#ifdef __GNUC__
#define _UNUSED __attribute__ ((unused))
#else
#define _UNUSED
#endif
enum {
kInterfaceVersion = 1 };
typedef struct OpContext OpContext;
struct OpContext
{
DNSServiceRef ServiceRef;
JNIEnv *Env;
jobject JavaObj;
jobject ClientObj;
jmethodID Callback;
jmethodID Callback2;
};
#if AUTO_CALLBACKS
JavaVM *gJavaVM = NULL;
#endif
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
jint callerVersion)
{
if ( callerVersion != kInterfaceVersion)
return kDNSServiceErr_Incompatible;
#if AUTO_CALLBACKS
{
jsize numVMs;
if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
return kDNSServiceErr_BadState;
}
#endif
{
#if AUTO_CALLBACKS
jboolean hasAutoC = JNI_TRUE;
#else
jboolean hasAutoC = JNI_FALSE;
#endif
jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
(*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
}
return kDNSServiceErr_NoError;
}
static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str)
{
return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
}
static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
{
if ( str != NULL)
(*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
}
#if AUTO_CALLBACKS
static void SetupCallbackState( JNIEnv **ppEnv)
{
(*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
}
static void TeardownCallbackState( void )
{
(*gJavaVM)->DetachCurrentThread( gJavaVM);
}
#else // AUTO_CALLBACKS
static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
{
}
static void TeardownCallbackState( void )
{
}
#endif // AUTO_CALLBACKS
static OpContext *NewContext( JNIEnv *pEnv, jobject owner,
const char *callbackName, const char *callbackSig)
{
OpContext *pContext = (OpContext*) malloc( sizeof *pContext);
if ( pContext != NULL)
{
jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
"fListener", "Lcom/apple/dnssd/BaseListener;");
pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField);
pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); pContext->Callback = (*pEnv)->GetMethodID( pEnv,
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
callbackName, callbackSig);
pContext->Callback2 = NULL; }
return pContext;
}
static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
"(Lcom/apple/dnssd/DNSSDService;I)V");
(*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
}
JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
if ( contextField != 0)
{
OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
if ( pContext != NULL)
{
(*pEnv)->SetIntField( pEnv, pThis, contextField, 0);
if ( pContext->ServiceRef != NULL)
DNSServiceRefDeallocate( pContext->ServiceRef);
(*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
(*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
free( pContext);
}
}
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis, jint msTimeout)
{
#if AUTO_CALLBACKS
return -1; #else // AUTO_CALLBACKS
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
jint rc = -1;
if ( contextField != 0)
{
OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
if ( pContext != NULL)
{
fd_set readFDs;
int sd = DNSServiceRefSockFD( pContext->ServiceRef);
struct timeval timeout = { msTimeout / 1000, 10 * (msTimeout % 1000) };
struct timeval *pTimeout = msTimeout == -1 ? NULL : &timeout;
FD_ZERO( &readFDs);
FD_SET( sd, &readFDs);
rc = select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, pTimeout);
}
}
return rc;
#endif // AUTO_CALLBACKS
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
{
#if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
DNSServiceErrorType err = kDNSServiceErr_BadState;
if ( pContext != NULL)
{
int sd = DNSServiceRefSockFD( pContext->ServiceRef);
fd_set readFDs;
struct timeval zeroTimeout = { 0, 0 };
pContext->Env = pEnv;
FD_ZERO( &readFDs);
FD_SET( sd, &readFDs);
err = kDNSServiceErr_NoError;
if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
{
err = DNSServiceProcessResult(pContext->ServiceRef);
}
}
return err;
#endif // AUTO_CALLBACKS
}
static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
const char *replyDomain, void *context)
{
OpContext *pContext = (OpContext*) context;
SetupCallbackState( &pContext->Env);
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
{
if ( errorCode == kDNSServiceErr_NoError)
{
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
pContext->JavaObj, flags, interfaceIndex,
(*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
(*pContext->Env)->NewStringUTF( pContext->Env, regtype),
(*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
}
else
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
}
TeardownCallbackState();
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
jint flags, jint ifIndex, jstring regType, jstring domain)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
if ( contextField != 0)
pContext = NewContext( pEnv, pThis, "serviceFound",
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
else
err = kDNSServiceErr_BadParam;
if ( pContext != NULL)
{
const char *regStr = SafeGetUTFChars( pEnv, regType);
const char *domainStr = SafeGetUTFChars( pEnv, domain);
pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
"serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
}
SafeReleaseUTFChars( pEnv, regType, regStr);
SafeReleaseUTFChars( pEnv, domain, domainStr);
}
else
err = kDNSServiceErr_NoMemory;
return err;
}
static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget,
uint16_t port, uint16_t txtLen, const char *txtRecord, void *context)
{
OpContext *pContext = (OpContext*) context;
jclass txtCls;
jmethodID txtCtor;
jbyteArray txtBytes;
jobject txtObj;
jbyte *pBytes;
SetupCallbackState( &pContext->Env);
txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
{
if ( errorCode == kDNSServiceErr_NoError)
{
port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL);
memcpy( pBytes, txtRecord, txtLen);
(*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT);
txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
(*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
pContext->JavaObj, flags, interfaceIndex,
(*pContext->Env)->NewStringUTF( pContext->Env, fullname),
(*pContext->Env)->NewStringUTF( pContext->Env, hosttarget),
port, txtObj);
}
else
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
}
TeardownCallbackState();
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis,
jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
if ( contextField != 0)
pContext = NewContext( pEnv, pThis, "serviceResolved",
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
else
err = kDNSServiceErr_BadParam;
if ( pContext != NULL)
{
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
const char *regStr = SafeGetUTFChars( pEnv, regType);
const char *domainStr = SafeGetUTFChars( pEnv, domain);
err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
servStr, regStr, domainStr, ServiceResolveReply, pContext);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
}
SafeReleaseUTFChars( pEnv, serviceName, servStr);
SafeReleaseUTFChars( pEnv, regType, regStr);
SafeReleaseUTFChars( pEnv, domain, domainStr);
}
else
err = kDNSServiceErr_NoMemory;
return err;
}
static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *serviceName,
const char *regType, const char *domain, void *context)
{
OpContext *pContext = (OpContext*) context;
SetupCallbackState( &pContext->Env);
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
{
if ( errorCode == kDNSServiceErr_NoError)
{
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
pContext->JavaObj, flags,
(*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
(*pContext->Env)->NewStringUTF( pContext->Env, regType),
(*pContext->Env)->NewStringUTF( pContext->Env, domain));
}
else
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
}
TeardownCallbackState();
}
JNIEXPORT jint JNICALL 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)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
jbyte *pBytes;
jsize numBytes;
if ( contextField != 0)
pContext = NewContext( pEnv, pThis, "serviceRegistered",
"(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
else
err = kDNSServiceErr_BadParam;
if ( pContext != NULL)
{
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
const char *regStr = SafeGetUTFChars( pEnv, regType);
const char *domainStr = SafeGetUTFChars( pEnv, domain);
const char *hostStr = SafeGetUTFChars( pEnv, host);
uint16_t portBits = port;
portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1];
pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
domainStr, hostStr, portBits,
numBytes, pBytes, ServiceRegisterReply, pContext);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
}
if ( pBytes != NULL)
(*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
SafeReleaseUTFChars( pEnv, serviceName, servStr);
SafeReleaseUTFChars( pEnv, regType, regStr);
SafeReleaseUTFChars( pEnv, domain, domainStr);
SafeReleaseUTFChars( pEnv, host, hostStr);
}
else
err = kDNSServiceErr_NoMemory;
return err;
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis,
jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
jbyte *pBytes;
jsize numBytes;
DNSRecordRef recRef;
if ( contextField != 0)
pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField);
if ( pContext == NULL || pContext->ServiceRef == NULL)
return kDNSServiceErr_BadParam;
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetIntField( pEnv, destObj, recField, (jint) recRef);
}
if ( pBytes != NULL)
(*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
return err;
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis,
jint flags, jbyteArray rData, jint ttl)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
jbyte *pBytes;
jsize numBytes;
DNSRecordRef recRef = NULL;
if ( ownerField != 0)
{
jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "I");
if ( contextField != 0)
pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, ownerObj, contextField);
}
if ( recField != 0)
recRef = (DNSRecordRef) (*pEnv)->GetIntField( pEnv, pThis, recField);
if ( pContext == NULL || pContext->ServiceRef == NULL)
return kDNSServiceErr_BadParam;
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
if ( pBytes != NULL)
(*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
return err;
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
DNSRecordRef recRef = NULL;
if ( ownerField != 0)
{
jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "I");
if ( contextField != 0)
pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, ownerObj, contextField);
}
if ( recField != 0)
recRef = (DNSRecordRef) (*pEnv)->GetIntField( pEnv, pThis, recField);
if ( pContext == NULL || pContext->ServiceRef == NULL)
return kDNSServiceErr_BadParam;
err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
return err;
}
static void DNSSD_API 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)
{
OpContext *pContext = (OpContext*) context;
jbyteArray rDataObj;
jbyte *pBytes;
SetupCallbackState( &pContext->Env);
if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
{
if ( errorCode == kDNSServiceErr_NoError)
{
pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL);
memcpy( pBytes, rdata, rdlen);
(*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT);
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
pContext->JavaObj, flags, interfaceIndex,
(*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
rrtype, rrclass, rDataObj, ttl);
}
else
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
}
TeardownCallbackState();
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis,
jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
if ( contextField != 0)
pContext = NewContext( pEnv, pThis, "queryAnswered",
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
else
err = kDNSServiceErr_BadParam;
if ( pContext != NULL)
{
const char *servStr = SafeGetUTFChars( pEnv, serviceName);
err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
rrtype, rrclass, ServiceQueryReply, pContext);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
}
SafeReleaseUTFChars( pEnv, serviceName, servStr);
}
else
err = kDNSServiceErr_NoMemory;
return err;
}
static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
DNSServiceErrorType errorCode, const char *replyDomain, void *context)
{
OpContext *pContext = (OpContext*) context;
SetupCallbackState( &pContext->Env);
if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
{
if ( errorCode == kDNSServiceErr_NoError)
{
(*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
pContext->JavaObj, flags, interfaceIndex,
(*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
}
else
ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
}
TeardownCallbackState();
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
jint flags, jint ifIndex)
{
jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I");
OpContext *pContext = NULL;
DNSServiceErrorType err = kDNSServiceErr_NoError;
if ( contextField != 0)
pContext = NewContext( pEnv, pThis, "domainFound",
"(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
else
err = kDNSServiceErr_BadParam;
if ( pContext != NULL)
{
pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
(*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
"domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
DomainEnumReply, pContext);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext);
}
}
else
err = kDNSServiceErr_NoMemory;
return err;
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
{
DNSServiceErrorType err = kDNSServiceErr_NoError;
const char *nameStr = SafeGetUTFChars( pEnv, serviceName);
const char *regStr = SafeGetUTFChars( pEnv, regtype);
const char *domStr = SafeGetUTFChars( pEnv, domain);
char buff[ kDNSServiceMaxDomainName + 1];
err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
if ( err == kDNSServiceErr_NoError)
{
(*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
}
SafeReleaseUTFChars( pEnv, serviceName, nameStr);
SafeReleaseUTFChars( pEnv, regtype, regStr);
SafeReleaseUTFChars( pEnv, domain, domStr);
return err;
}
JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED,
jint flags, jint ifIndex, jstring fullName,
jint rrtype, jint rrclass, jbyteArray rdata)
{
jbyte *pBytes;
jsize numBytes;
const char *nameStr = SafeGetUTFChars( pEnv, fullName);
pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
if ( pBytes != NULL)
(*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
SafeReleaseUTFChars( pEnv, fullName, nameStr);
}
#define LOCAL_ONLY_NAME "loo"
JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
jint ifIndex)
{
char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
if (ifIndex != kDNSServiceInterfaceIndexLocalOnly)
p = if_indextoname( ifIndex, nameBuff );
return (*pEnv)->NewStringUTF( pEnv, p);
}
JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED,
jstring ifName)
{
uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
const char *nameStr = SafeGetUTFChars( pEnv, ifName);
if (strcmp(nameStr, LOCAL_ONLY_NAME))
ifIndex = if_nametoindex( nameStr);
SafeReleaseUTFChars( pEnv, ifName, nameStr);
return ifIndex;
}
#if defined(_WIN32)
static char*
if_indextoname( DWORD ifIndex, char * nameBuff)
{
PIP_ADAPTER_INFO pAdapterInfo = NULL;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
char * ifName = NULL;
ULONG ulOutBufLen = 0;
if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
{
goto exit;
}
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
if (pAdapterInfo == NULL)
{
goto exit;
}
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
if (dwRetVal != NO_ERROR)
{
goto exit;
}
pAdapter = pAdapterInfo;
while (pAdapter)
{
if (pAdapter->Index == ifIndex)
{
strcpy( nameBuff, pAdapter->AdapterName );
ifName = nameBuff;
break;
}
pAdapter = pAdapter->Next;
}
exit:
if (pAdapterInfo != NULL)
{
free( pAdapterInfo );
pAdapterInfo = NULL;
}
return ifName;
}
static DWORD
if_nametoindex( const char * nameStr )
{
PIP_ADAPTER_INFO pAdapterInfo = NULL;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
DWORD ifIndex = 0;
ULONG ulOutBufLen = 0;
if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
{
goto exit;
}
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
if (pAdapterInfo == NULL)
{
goto exit;
}
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
if (dwRetVal != NO_ERROR)
{
goto exit;
}
pAdapter = pAdapterInfo;
while (pAdapter)
{
if (strcmp(pAdapter->AdapterName, nameStr) == 0)
{
ifIndex = pAdapter->Index;
break;
}
pAdapter = pAdapter->Next;
}
exit:
if (pAdapterInfo != NULL)
{
free( pAdapterInfo );
pAdapterInfo = NULL;
}
return ifIndex;
}
#endif