/* -*- 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
				)
{
}
