1235 lines
24 KiB
C++
Executable File
1235 lines
24 KiB
C++
Executable File
/* -*- Mode: C; tab-width: 4 -*-
|
|
*
|
|
* Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
// This is the main DLL file.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "dnssd_NET.h"
|
|
#include "DebugServices.h"
|
|
#include "PString.h"
|
|
|
|
|
|
using namespace System::Net::Sockets;
|
|
using namespace System::Diagnostics;
|
|
using namespace Apple;
|
|
using namespace Apple::DNSSD;
|
|
|
|
|
|
//===========================================================================================================================
|
|
// Constants
|
|
//===========================================================================================================================
|
|
|
|
#define DEBUG_NAME "[dnssd.NET] "
|
|
|
|
//
|
|
// ConvertToString
|
|
//
|
|
static String*
|
|
ConvertToString(const char * utf8String)
|
|
{
|
|
return __gc new String(utf8String, 0, strlen(utf8String), __gc new UTF8Encoding(true, true));
|
|
}
|
|
|
|
|
|
//
|
|
// class ServiceRef
|
|
//
|
|
// ServiceRef serves as the base class for all DNSService operations.
|
|
//
|
|
// It manages the DNSServiceRef, and implements processing the
|
|
// result
|
|
//
|
|
ServiceRef::ServiceRef(Object * callback)
|
|
:
|
|
m_bDisposed(false),
|
|
m_callback(callback),
|
|
m_thread(NULL)
|
|
{
|
|
m_impl = new ServiceRefImpl(this);
|
|
}
|
|
|
|
|
|
ServiceRef::~ServiceRef()
|
|
{
|
|
}
|
|
|
|
|
|
//
|
|
// StartThread
|
|
//
|
|
// Starts the main processing thread
|
|
//
|
|
void
|
|
ServiceRef::StartThread()
|
|
{
|
|
check( m_impl != NULL );
|
|
|
|
m_impl->SetupEvents();
|
|
|
|
m_thread = new Thread(new ThreadStart(this, &Apple::DNSSD::ServiceRef::ProcessingThread));
|
|
m_thread->Name = S"DNSService Thread";
|
|
m_thread->IsBackground = true;
|
|
|
|
m_thread->Start();
|
|
}
|
|
|
|
|
|
//
|
|
// ProcessingThread
|
|
//
|
|
// The Thread class can only invoke methods in MC++ types. So we
|
|
// make a ProcessingThread method that forwards to the impl
|
|
//
|
|
void
|
|
ServiceRef::ProcessingThread()
|
|
{
|
|
m_impl->ProcessingThread();
|
|
}
|
|
|
|
|
|
//
|
|
// Dispose
|
|
//
|
|
// Calls impl-Dispose(). This ultimately will call DNSServiceRefDeallocate()
|
|
//
|
|
void
|
|
ServiceRef::Dispose()
|
|
{
|
|
check(m_impl != NULL);
|
|
check(m_bDisposed == false);
|
|
|
|
if (!m_bDisposed)
|
|
{
|
|
m_bDisposed = true;
|
|
|
|
//
|
|
// Call Dispose. This won't call DNSServiceRefDeallocate()
|
|
// necessarily. It depends on what thread this is being
|
|
// called in.
|
|
//
|
|
m_impl->Dispose();
|
|
m_impl = NULL;
|
|
|
|
m_thread = NULL;
|
|
|
|
GC::SuppressFinalize(this);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// EnumerateDomainsDispatch
|
|
//
|
|
// Dispatch a reply to the delegate.
|
|
//
|
|
void
|
|
ServiceRef::EnumerateDomainsDispatch
|
|
(
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
ErrorCode errorCode,
|
|
String * replyDomain
|
|
)
|
|
{
|
|
if ((m_callback != NULL) && (m_impl != NULL))
|
|
{
|
|
DNSService::EnumerateDomainsReply * OnEnumerateDomainsReply = static_cast<DNSService::EnumerateDomainsReply*>(m_callback);
|
|
OnEnumerateDomainsReply(this, flags, interfaceIndex, errorCode, replyDomain);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// RegisterDispatch
|
|
//
|
|
// Dispatch a reply to the delegate.
|
|
//
|
|
void
|
|
ServiceRef::RegisterDispatch
|
|
(
|
|
ServiceFlags flags,
|
|
ErrorCode errorCode,
|
|
String * name,
|
|
String * regtype,
|
|
String * domain
|
|
)
|
|
{
|
|
if ((m_callback != NULL) && (m_impl != NULL))
|
|
{
|
|
DNSService::RegisterReply * OnRegisterReply = static_cast<DNSService::RegisterReply*>(m_callback);
|
|
OnRegisterReply(this, flags, errorCode, name, regtype, domain);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// BrowseDispatch
|
|
//
|
|
// Dispatch a reply to the delegate.
|
|
//
|
|
void
|
|
ServiceRef::BrowseDispatch
|
|
(
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
ErrorCode errorCode,
|
|
String * serviceName,
|
|
String * regtype,
|
|
String * replyDomain
|
|
)
|
|
{
|
|
if ((m_callback != NULL) && (m_impl != NULL))
|
|
{
|
|
DNSService::BrowseReply * OnBrowseReply = static_cast<DNSService::BrowseReply*>(m_callback);
|
|
OnBrowseReply(this, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ResolveDispatch
|
|
//
|
|
// Dispatch a reply to the delegate.
|
|
//
|
|
void
|
|
ServiceRef::ResolveDispatch
|
|
(
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
ErrorCode errorCode,
|
|
String * fullname,
|
|
String * hosttarget,
|
|
int port,
|
|
Byte txtRecord[]
|
|
)
|
|
{
|
|
if ((m_callback != NULL) && (m_impl != NULL))
|
|
{
|
|
DNSService::ResolveReply * OnResolveReply = static_cast<DNSService::ResolveReply*>(m_callback);
|
|
OnResolveReply(this, flags, interfaceIndex, errorCode, fullname, hosttarget, port, txtRecord);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// RegisterRecordDispatch
|
|
//
|
|
// Dispatch a reply to the delegate.
|
|
//
|
|
void
|
|
ServiceRef::RegisterRecordDispatch
|
|
(
|
|
ServiceFlags flags,
|
|
ErrorCode errorCode,
|
|
RecordRef * record
|
|
)
|
|
{
|
|
if ((m_callback != NULL) && (m_impl != NULL))
|
|
{
|
|
DNSService::RegisterRecordReply * OnRegisterRecordReply = static_cast<DNSService::RegisterRecordReply*>(m_callback);
|
|
OnRegisterRecordReply(this, flags, errorCode, record);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// QueryRecordDispatch
|
|
//
|
|
// Dispatch a reply to the delegate.
|
|
//
|
|
void
|
|
ServiceRef::QueryRecordDispatch
|
|
(
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
ErrorCode errorCode,
|
|
String * fullname,
|
|
int rrtype,
|
|
int rrclass,
|
|
Byte rdata[],
|
|
int ttl
|
|
)
|
|
{
|
|
if ((m_callback != NULL) && (m_impl != NULL))
|
|
{
|
|
DNSService::QueryRecordReply * OnQueryRecordReply = static_cast<DNSService::QueryRecordReply*>(m_callback);
|
|
OnQueryRecordReply(this, flags, interfaceIndex, errorCode, fullname, rrtype, rrclass, rdata, ttl);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::ServiceRefImpl()
|
|
//
|
|
// Constructs a new ServiceRefImpl. We save the pointer to our enclosing
|
|
// class in a gcroot handle. This satisfies the garbage collector as
|
|
// the outer class is a managed type
|
|
//
|
|
ServiceRef::ServiceRefImpl::ServiceRefImpl(ServiceRef * outer)
|
|
:
|
|
m_socketEvent(NULL),
|
|
m_stopEvent(NULL),
|
|
m_disposed(false),
|
|
m_outer(outer),
|
|
m_ref(NULL)
|
|
{
|
|
m_threadId = GetCurrentThreadId();
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::~ServiceRefImpl()
|
|
//
|
|
// Deallocate all resources associated with the ServiceRefImpl
|
|
//
|
|
ServiceRef::ServiceRefImpl::~ServiceRefImpl()
|
|
{
|
|
if (m_socketEvent != NULL)
|
|
{
|
|
CloseHandle(m_socketEvent);
|
|
m_socketEvent = NULL;
|
|
}
|
|
|
|
if (m_stopEvent != NULL)
|
|
{
|
|
CloseHandle(m_stopEvent);
|
|
m_stopEvent = NULL;
|
|
}
|
|
|
|
if (m_ref != NULL)
|
|
{
|
|
DNSServiceRefDeallocate(m_ref);
|
|
m_ref = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::SetupEvents()
|
|
//
|
|
// Setup the events necessary to manage multi-threaded dispatch
|
|
// of DNSService Events
|
|
//
|
|
void
|
|
ServiceRef::ServiceRefImpl::SetupEvents()
|
|
{
|
|
check(m_ref != NULL);
|
|
|
|
m_socket = (SOCKET) DNSServiceRefSockFD(m_ref);
|
|
check(m_socket != INVALID_SOCKET);
|
|
|
|
m_socketEvent = CreateEvent(NULL, 0, 0, NULL);
|
|
|
|
if (m_socketEvent == NULL)
|
|
{
|
|
throw new DNSServiceException(Unknown);
|
|
}
|
|
|
|
int err = WSAEventSelect(m_socket, m_socketEvent, FD_READ|FD_CLOSE);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(Unknown);
|
|
}
|
|
|
|
m_stopEvent = CreateEvent(NULL, 0, 0, NULL);
|
|
|
|
if (m_stopEvent == NULL)
|
|
{
|
|
throw new DNSServiceException(Unknown);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::ProcessingThread()
|
|
//
|
|
// Wait for socket events on the DNSServiceRefSockFD(). Also wait
|
|
// for stop events
|
|
//
|
|
void
|
|
ServiceRef::ServiceRefImpl::ProcessingThread()
|
|
{
|
|
check( m_socketEvent != NULL );
|
|
check( m_stopEvent != NULL );
|
|
check( m_ref != NULL );
|
|
|
|
HANDLE handles[2];
|
|
|
|
handles[0] = m_socketEvent;
|
|
handles[1] = m_stopEvent;
|
|
|
|
while (m_disposed == false)
|
|
{
|
|
int ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
|
|
|
//
|
|
// it's a socket event
|
|
//
|
|
if (ret == WAIT_OBJECT_0)
|
|
{
|
|
DNSServiceProcessResult(m_ref);
|
|
}
|
|
//
|
|
// else it's a stop event
|
|
//
|
|
else if (ret == WAIT_OBJECT_0 + 1)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// unexpected wait result
|
|
//
|
|
dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, ret );
|
|
}
|
|
}
|
|
|
|
delete this;
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::Dispose()
|
|
//
|
|
// Calls DNSServiceRefDeallocate()
|
|
//
|
|
void
|
|
ServiceRef::ServiceRefImpl::Dispose()
|
|
{
|
|
OSStatus err;
|
|
BOOL ok;
|
|
|
|
check(m_disposed == false);
|
|
|
|
m_disposed = true;
|
|
|
|
ok = SetEvent(m_stopEvent);
|
|
err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
|
|
require_noerr( err, exit );
|
|
|
|
exit:
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::EnumerateDomainsCallback()
|
|
//
|
|
// This is the callback from dnssd.dll. We pass this up to our outer, managed type
|
|
//
|
|
void DNSSD_API
|
|
ServiceRef::ServiceRefImpl::EnumerateDomainsCallback
|
|
(
|
|
DNSServiceRef sdRef,
|
|
DNSServiceFlags flags,
|
|
uint32_t interfaceIndex,
|
|
DNSServiceErrorType errorCode,
|
|
const char * replyDomain,
|
|
void * context
|
|
)
|
|
{
|
|
ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
|
|
|
|
check( self != NULL );
|
|
check( self->m_outer != NULL );
|
|
|
|
if (self->m_disposed == false)
|
|
{
|
|
self->m_outer->EnumerateDomainsDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(replyDomain));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::RegisterCallback()
|
|
//
|
|
// This is the callback from dnssd.dll. We pass this up to our outer, managed type
|
|
//
|
|
void DNSSD_API
|
|
ServiceRef::ServiceRefImpl::RegisterCallback
|
|
(
|
|
DNSServiceRef sdRef,
|
|
DNSServiceFlags flags,
|
|
DNSServiceErrorType errorCode,
|
|
const char * name,
|
|
const char * regtype,
|
|
const char * domain,
|
|
void * context
|
|
)
|
|
{
|
|
ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
|
|
|
|
check( self != NULL );
|
|
check( self->m_outer != NULL );
|
|
|
|
if (self->m_disposed == false)
|
|
{
|
|
self->m_outer->RegisterDispatch((ServiceFlags) flags, (ErrorCode) errorCode, ConvertToString(name), ConvertToString(regtype), ConvertToString(domain));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::BrowseCallback()
|
|
//
|
|
// This is the callback from dnssd.dll. We pass this up to our outer, managed type
|
|
//
|
|
void DNSSD_API
|
|
ServiceRef::ServiceRefImpl::BrowseCallback
|
|
(
|
|
DNSServiceRef sdRef,
|
|
DNSServiceFlags flags,
|
|
uint32_t interfaceIndex,
|
|
DNSServiceErrorType errorCode,
|
|
const char * serviceName,
|
|
const char * regtype,
|
|
const char * replyDomain,
|
|
void * context
|
|
)
|
|
{
|
|
ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
|
|
|
|
check( self != NULL );
|
|
check( self->m_outer != NULL );
|
|
|
|
if (self->m_disposed == false)
|
|
{
|
|
self->m_outer->BrowseDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(serviceName), ConvertToString(regtype), ConvertToString(replyDomain));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::ResolveCallback()
|
|
//
|
|
// This is the callback from dnssd.dll. We pass this up to our outer, managed type
|
|
//
|
|
void DNSSD_API
|
|
ServiceRef::ServiceRefImpl::ResolveCallback
|
|
(
|
|
DNSServiceRef sdRef,
|
|
DNSServiceFlags flags,
|
|
uint32_t interfaceIndex,
|
|
DNSServiceErrorType errorCode,
|
|
const char * fullname,
|
|
const char * hosttarget,
|
|
uint16_t notAnIntPort,
|
|
uint16_t txtLen,
|
|
const char * txtRecord,
|
|
void * context
|
|
)
|
|
{
|
|
ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
|
|
|
|
check( self != NULL );
|
|
check( self->m_outer != NULL );
|
|
|
|
if (self->m_disposed == false)
|
|
{
|
|
Byte txtRecordBytes[];
|
|
|
|
txtRecordBytes = NULL;
|
|
|
|
if (txtLen > 0)
|
|
{
|
|
//
|
|
// copy raw memory into managed byte array
|
|
//
|
|
txtRecordBytes = new Byte[txtLen];
|
|
Byte __pin * p = &txtRecordBytes[0];
|
|
memcpy(p, txtRecord, txtLen);
|
|
}
|
|
|
|
self->m_outer->ResolveDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(fullname), ConvertToString(hosttarget), ntohs(notAnIntPort), txtRecordBytes);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::RegisterRecordCallback()
|
|
//
|
|
// This is the callback from dnssd.dll. We pass this up to our outer, managed type
|
|
//
|
|
void DNSSD_API
|
|
ServiceRef::ServiceRefImpl::RegisterRecordCallback
|
|
(
|
|
DNSServiceRef sdRef,
|
|
DNSRecordRef rrRef,
|
|
DNSServiceFlags flags,
|
|
DNSServiceErrorType errorCode,
|
|
void * context
|
|
)
|
|
{
|
|
ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
|
|
|
|
check( self != NULL );
|
|
check( self->m_outer != NULL );
|
|
|
|
if (self->m_disposed == false)
|
|
{
|
|
RecordRef * record = NULL;
|
|
|
|
if (errorCode == 0)
|
|
{
|
|
record = new RecordRef;
|
|
|
|
record->m_impl->m_ref = rrRef;
|
|
}
|
|
|
|
self->m_outer->RegisterRecordDispatch((ServiceFlags) flags, (ErrorCode) errorCode, record);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ServiceRefImpl::QueryRecordCallback()
|
|
//
|
|
// This is the callback from dnssd.dll. We pass this up to our outer, managed type
|
|
//
|
|
void DNSSD_API
|
|
ServiceRef::ServiceRefImpl::QueryRecordCallback
|
|
(
|
|
DNSServiceRef DNSServiceRef,
|
|
DNSServiceFlags flags,
|
|
uint32_t interfaceIndex,
|
|
DNSServiceErrorType errorCode,
|
|
const char * fullname,
|
|
uint16_t rrtype,
|
|
uint16_t rrclass,
|
|
uint16_t rdlen,
|
|
const void * rdata,
|
|
uint32_t ttl,
|
|
void * context
|
|
)
|
|
{
|
|
ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
|
|
|
|
check( self != NULL );
|
|
check( self->m_outer != NULL );
|
|
|
|
if (self->m_disposed == false)
|
|
{
|
|
Byte rdataBytes[];
|
|
|
|
if (rdlen)
|
|
{
|
|
rdataBytes = new Byte[rdlen];
|
|
Byte __pin * p = &rdataBytes[0];
|
|
memcpy(p, rdata, rdlen);
|
|
}
|
|
|
|
self->m_outer->QueryRecordDispatch((ServiceFlags) flags, (int) interfaceIndex, (ErrorCode) errorCode, ConvertToString(fullname), rrtype, rrclass, rdataBytes, ttl);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* EnumerateDomains()
|
|
*
|
|
* This maps to DNSServiceEnumerateDomains(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
ServiceRef*
|
|
DNSService::EnumerateDomains
|
|
(
|
|
int flags,
|
|
int interfaceIndex,
|
|
EnumerateDomainsReply * callback
|
|
)
|
|
{
|
|
ServiceRef * sdRef = new ServiceRef(callback);
|
|
int err;
|
|
|
|
err = DNSServiceEnumerateDomains(&sdRef->m_impl->m_ref, flags, interfaceIndex, ServiceRef::ServiceRefImpl::EnumerateDomainsCallback, sdRef->m_impl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
sdRef->StartThread();
|
|
|
|
return sdRef;
|
|
}
|
|
|
|
|
|
/*
|
|
* Register()
|
|
*
|
|
* This maps to DNSServiceRegister(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
ServiceRef*
|
|
DNSService::Register
|
|
(
|
|
int flags,
|
|
int interfaceIndex,
|
|
String * name,
|
|
String * regtype,
|
|
String * domain,
|
|
String * host,
|
|
int port,
|
|
Byte txtRecord[],
|
|
RegisterReply * callback
|
|
)
|
|
{
|
|
ServiceRef * sdRef = new ServiceRef(callback);
|
|
PString * pName = new PString(name);
|
|
PString * pType = new PString(regtype);
|
|
PString * pDomain = new PString(domain);
|
|
PString * pHost = new PString(host);
|
|
int len = 0;
|
|
Byte __pin * p = NULL;
|
|
void * v = NULL;
|
|
|
|
if ((txtRecord != NULL) && (txtRecord->Length > 0))
|
|
{
|
|
len = txtRecord->Length;
|
|
p = &txtRecord[0];
|
|
v = (void*) p;
|
|
}
|
|
|
|
int err = DNSServiceRegister(&sdRef->m_impl->m_ref, flags, interfaceIndex, pName->c_str(), pType->c_str(), pDomain->c_str(), pHost->c_str(), htons(port), len, v, ServiceRef::ServiceRefImpl::RegisterCallback, sdRef->m_impl );
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
sdRef->StartThread();
|
|
|
|
return sdRef;
|
|
}
|
|
|
|
|
|
/*
|
|
* AddRecord()
|
|
*
|
|
* This maps to DNSServiceAddRecord(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
RecordRef*
|
|
DNSService::AddRecord
|
|
(
|
|
ServiceRef * sdRef,
|
|
int flags,
|
|
int rrtype,
|
|
Byte rdata[],
|
|
int ttl
|
|
)
|
|
{
|
|
int len = 0;
|
|
Byte __pin * p = NULL;
|
|
void * v = NULL;
|
|
|
|
if ((rdata != NULL) && (rdata->Length > 0))
|
|
{
|
|
len = rdata->Length;
|
|
p = &rdata[0];
|
|
v = (void*) p;
|
|
}
|
|
|
|
RecordRef * record = new RecordRef;
|
|
|
|
int err = DNSServiceAddRecord(sdRef->m_impl->m_ref, &record->m_impl->m_ref, flags, rrtype, len, v, ttl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
return record;
|
|
}
|
|
|
|
|
|
/*
|
|
* UpdateRecord()
|
|
*
|
|
* This maps to DNSServiceUpdateRecord(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
void
|
|
DNSService::UpdateRecord
|
|
(
|
|
ServiceRef * sdRef,
|
|
RecordRef * record,
|
|
int flags,
|
|
Byte rdata[],
|
|
int ttl
|
|
)
|
|
{
|
|
int len = 0;
|
|
Byte __pin * p = NULL;
|
|
void * v = NULL;
|
|
|
|
if ((rdata != NULL) && (rdata->Length > 0))
|
|
{
|
|
len = rdata->Length;
|
|
p = &rdata[0];
|
|
v = (void*) p;
|
|
}
|
|
|
|
int err = DNSServiceUpdateRecord(sdRef->m_impl->m_ref, record ? record->m_impl->m_ref : NULL, flags, len, v, ttl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* RemoveRecord()
|
|
*
|
|
* This maps to DNSServiceRemoveRecord(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
void
|
|
DNSService::RemoveRecord
|
|
(
|
|
ServiceRef * sdRef,
|
|
RecordRef * record,
|
|
int flags
|
|
)
|
|
{
|
|
int err = DNSServiceRemoveRecord(sdRef->m_impl->m_ref, record->m_impl->m_ref, flags);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Browse()
|
|
*
|
|
* This maps to DNSServiceBrowse(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
ServiceRef*
|
|
DNSService::Browse
|
|
(
|
|
int flags,
|
|
int interfaceIndex,
|
|
String * regtype,
|
|
String * domain,
|
|
BrowseReply * callback
|
|
)
|
|
{
|
|
ServiceRef * sdRef = new ServiceRef(callback);
|
|
PString * pType = new PString(regtype);
|
|
PString * pDomain = new PString(domain);
|
|
|
|
int err = DNSServiceBrowse(&sdRef->m_impl->m_ref, flags, interfaceIndex, pType->c_str(), pDomain->c_str(),(DNSServiceBrowseReply) ServiceRef::ServiceRefImpl::BrowseCallback, sdRef->m_impl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
sdRef->StartThread();
|
|
|
|
return sdRef;
|
|
}
|
|
|
|
|
|
/*
|
|
* Resolve()
|
|
*
|
|
* This maps to DNSServiceResolve(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
ServiceRef*
|
|
DNSService::Resolve
|
|
(
|
|
int flags,
|
|
int interfaceIndex,
|
|
String * name,
|
|
String * regtype,
|
|
String * domain,
|
|
ResolveReply * callback
|
|
)
|
|
{
|
|
ServiceRef * sdRef = new ServiceRef(callback);
|
|
PString * pName = new PString(name);
|
|
PString * pType = new PString(regtype);
|
|
PString * pDomain = new PString(domain);
|
|
|
|
int err = DNSServiceResolve(&sdRef->m_impl->m_ref, flags, interfaceIndex, pName->c_str(), pType->c_str(), pDomain->c_str(),(DNSServiceResolveReply) ServiceRef::ServiceRefImpl::ResolveCallback, sdRef->m_impl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
sdRef->StartThread();
|
|
|
|
return sdRef;
|
|
}
|
|
|
|
|
|
/*
|
|
* CreateConnection()
|
|
*
|
|
* This maps to DNSServiceCreateConnection(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
ServiceRef*
|
|
DNSService::CreateConnection
|
|
(
|
|
RegisterRecordReply * callback
|
|
)
|
|
{
|
|
ServiceRef * sdRef = new ServiceRef(callback);
|
|
|
|
int err = DNSServiceCreateConnection(&sdRef->m_impl->m_ref);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
sdRef->StartThread();
|
|
|
|
return sdRef;
|
|
}
|
|
|
|
|
|
/*
|
|
* RegisterRecord()
|
|
*
|
|
* This maps to DNSServiceRegisterRecord(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
|
|
RecordRef*
|
|
DNSService::RegisterRecord
|
|
(
|
|
ServiceRef * sdRef,
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
String * fullname,
|
|
int rrtype,
|
|
int rrclass,
|
|
Byte rdata[],
|
|
int ttl
|
|
)
|
|
{
|
|
RecordRef * record = new RecordRef;
|
|
int len = 0;
|
|
Byte __pin * p = NULL;
|
|
void * v = NULL;
|
|
|
|
PString * pFullname = new PString(fullname);
|
|
|
|
if ((rdata != NULL) && (rdata->Length > 0))
|
|
{
|
|
len = rdata->Length;
|
|
p = &rdata[0];
|
|
v = (void*) p;
|
|
}
|
|
|
|
int err = DNSServiceRegisterRecord(sdRef->m_impl->m_ref, &record->m_impl->m_ref, flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, len, v, ttl, (DNSServiceRegisterRecordReply) ServiceRef::ServiceRefImpl::RegisterRecordCallback, sdRef->m_impl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
return record;
|
|
}
|
|
|
|
/*
|
|
* QueryRecord()
|
|
*
|
|
* This maps to DNSServiceQueryRecord(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
ServiceRef*
|
|
DNSService::QueryRecord
|
|
(
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
String * fullname,
|
|
int rrtype,
|
|
int rrclass,
|
|
QueryRecordReply * callback
|
|
)
|
|
{
|
|
ServiceRef * sdRef = new ServiceRef(callback);
|
|
PString * pFullname = new PString(fullname);
|
|
|
|
int err = DNSServiceQueryRecord(&sdRef->m_impl->m_ref, flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, (DNSServiceQueryRecordReply) ServiceRef::ServiceRefImpl::QueryRecordCallback, sdRef->m_impl);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
sdRef->StartThread();
|
|
|
|
return sdRef;
|
|
}
|
|
|
|
|
|
/*
|
|
* ReconfirmRecord()
|
|
*
|
|
* This maps to DNSServiceReconfirmRecord(). Returns an
|
|
* initialized ServiceRef on success, throws an exception
|
|
* on failure.
|
|
*/
|
|
void
|
|
DNSService::ReconfirmRecord
|
|
(
|
|
ServiceFlags flags,
|
|
int interfaceIndex,
|
|
String * fullname,
|
|
int rrtype,
|
|
int rrclass,
|
|
Byte rdata[]
|
|
)
|
|
{
|
|
int len = 0;
|
|
Byte __pin * p = NULL;
|
|
void * v = NULL;
|
|
|
|
PString * pFullname = new PString(fullname);
|
|
|
|
if ((rdata != NULL) && (rdata->Length > 0))
|
|
{
|
|
len = rdata->Length;
|
|
p = &rdata[0];
|
|
v = (void*) p;
|
|
}
|
|
|
|
DNSServiceReconfirmRecord(flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, len, v);
|
|
}
|
|
|
|
|
|
void
|
|
TextRecord::SetValue
|
|
(
|
|
String * key,
|
|
Byte value[] /* may be NULL */
|
|
)
|
|
{
|
|
PString * pKey = new PString(key);
|
|
int len = 0;
|
|
Byte __pin * p = NULL;
|
|
void * v = NULL;
|
|
DNSServiceErrorType err;
|
|
|
|
if (value && (value->Length > 0))
|
|
{
|
|
len = value->Length;
|
|
p = &value[0];
|
|
v = (void*) p;
|
|
}
|
|
|
|
err = TXTRecordSetValue(&m_impl->m_ref, pKey->c_str(), len, v);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
TextRecord::RemoveValue
|
|
(
|
|
String * key
|
|
)
|
|
{
|
|
PString * pKey = new PString(key);
|
|
DNSServiceErrorType err;
|
|
|
|
err = TXTRecordRemoveValue(&m_impl->m_ref, pKey->c_str());
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
TextRecord::GetLength
|
|
(
|
|
)
|
|
{
|
|
return TXTRecordGetLength(&m_impl->m_ref);
|
|
}
|
|
|
|
|
|
Byte
|
|
TextRecord::GetBytes
|
|
(
|
|
) __gc[]
|
|
{
|
|
const void * noGCBytes = NULL;
|
|
Byte gcBytes[] = NULL;
|
|
|
|
noGCBytes = TXTRecordGetBytesPtr(&m_impl->m_ref);
|
|
int len = GetLength();
|
|
|
|
if (noGCBytes && len)
|
|
{
|
|
gcBytes = new Byte[len];
|
|
Byte __pin * p = &gcBytes[0];
|
|
memcpy(p, noGCBytes, len);
|
|
}
|
|
|
|
return gcBytes;
|
|
}
|
|
|
|
|
|
bool
|
|
TextRecord::ContainsKey
|
|
(
|
|
Byte txtRecord[],
|
|
String * key
|
|
)
|
|
{
|
|
PString * pKey = new PString(key);
|
|
Byte __pin * p = &txtRecord[0];
|
|
|
|
return (TXTRecordContainsKey(txtRecord->Length, p, pKey->c_str()) > 0) ? true : false;
|
|
}
|
|
|
|
|
|
Byte
|
|
TextRecord::GetValueBytes
|
|
(
|
|
Byte txtRecord[],
|
|
String * key
|
|
) __gc[]
|
|
{
|
|
uint8_t valueLen;
|
|
Byte ret[] = NULL;
|
|
PString * pKey = new PString(key);
|
|
Byte __pin * p1 = &txtRecord[0];
|
|
const void * v;
|
|
|
|
v = TXTRecordGetValuePtr(txtRecord->Length, p1, pKey->c_str(), &valueLen);
|
|
|
|
if (v != NULL)
|
|
{
|
|
ret = new Byte[valueLen];
|
|
Byte __pin * p2 = &ret[0];
|
|
|
|
memcpy(p2, v, valueLen);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int
|
|
TextRecord::GetCount
|
|
(
|
|
Byte txtRecord[]
|
|
)
|
|
{
|
|
Byte __pin * p = &txtRecord[0];
|
|
|
|
return TXTRecordGetCount(txtRecord->Length, p);
|
|
}
|
|
|
|
|
|
Byte
|
|
TextRecord::GetItemAtIndex
|
|
(
|
|
Byte txtRecord[],
|
|
int index,
|
|
[Out] String ** key
|
|
) __gc[]
|
|
{
|
|
char keyBuf[255];
|
|
uint8_t keyBufLen = 255;
|
|
uint8_t valueLen;
|
|
void * value;
|
|
Byte ret[] = NULL;
|
|
DNSServiceErrorType err;
|
|
Byte __pin * p1 = &txtRecord[0];
|
|
|
|
|
|
err = TXTRecordGetItemAtIndex(txtRecord->Length, p1, index, keyBufLen, keyBuf, &valueLen, (const void**) &value);
|
|
|
|
if (err != 0)
|
|
{
|
|
throw new DNSServiceException(err);
|
|
}
|
|
|
|
*key = ConvertToString(keyBuf);
|
|
|
|
if (valueLen)
|
|
{
|
|
ret = new Byte[valueLen];
|
|
Byte __pin * p2 = &ret[0];
|
|
|
|
memcpy(p2, value, valueLen);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
//
|
|
// DNSServiceException::DNSServiceException()
|
|
//
|
|
// Constructs an exception with an error code
|
|
//
|
|
DNSServiceException::DNSServiceException
|
|
(
|
|
int _err
|
|
)
|
|
:
|
|
err(_err)
|
|
{
|
|
}
|
|
|
|
|
|
//
|
|
// This version of the constructor is useful for instances in which
|
|
// an inner exception is thrown, caught, and then a new exception
|
|
// is thrown in it's place
|
|
//
|
|
DNSServiceException::DNSServiceException
|
|
(
|
|
String * message,
|
|
System::Exception * innerException
|
|
)
|
|
{
|
|
}
|