/* -*- Mode: C; tab-width: 4 -*-
 *
 * Copyright (c) 2009 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.
 */



#pragma warning(disable:4995)



#include "stdafx.h"

#include <strsafe.h>

#include "DNSSDService.h"

#include "DNSSDEventManager.h"

#include "DNSSDRecord.h"

#include "TXTRecord.h"

#include "StringServices.h"

#include <DebugServices.h>





#define WM_SOCKET (WM_APP + 100)





// CDNSSDService



BOOL						CDNSSDService::m_registeredWindowClass	= FALSE;

HWND						CDNSSDService::m_hiddenWindow			= NULL;

CDNSSDService::SocketMap	CDNSSDService::m_socketMap;





HRESULT CDNSSDService::FinalConstruct()

{

	DNSServiceErrorType	err	= 0;

	HRESULT				hr	= S_OK;



	m_isPrimary = TRUE;

	err = DNSServiceCreateConnection( &m_primary );

	require_action( !err, exit, hr = E_FAIL );



	if ( !m_hiddenWindow )

	{

		TCHAR windowClassName[ 256 ];



		StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) );



		if ( !m_registeredWindowClass )

		{

			WNDCLASS	wc;

			ATOM		atom;



			wc.style			= 0;

			wc.lpfnWndProc		= WndProc;

			wc.cbClsExtra		= 0;

			wc.cbWndExtra		= 0;

			wc.hInstance		= NULL;

			wc.hIcon			= NULL;

			wc.hCursor			= NULL;

			wc.hbrBackground	= NULL;

			wc.lpszMenuName		= NULL;

			wc.lpszClassName	= windowClassName;



			atom = RegisterClass(&wc);

			require_action( atom != NULL, exit, hr = E_FAIL );



			m_registeredWindowClass = TRUE;

		}



		m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL );

		require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL );

	}



	err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ );

	require_action( !err, exit, hr = E_FAIL );



	m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this;



exit:



	return hr;

}





void CDNSSDService::FinalRelease()

{

	dlog( kDebugLevelTrace, "FinalRelease()\n" ); 

	Stop();

}





STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service)

{

	CComObject<CDNSSDService>	*	object	= NULL;

	DNSServiceRef					subord	= NULL;

	DNSServiceErrorType				err		= 0;

	HRESULT							hr		= 0;



	check( m_primary );



	// Initialize

	*service = NULL;



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	subord = m_primary;

	err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service )

{

	CComObject<CDNSSDService>	*	object		= NULL;

	std::string						regtypeUTF8;

	std::string						domainUTF8;

	DNSServiceRef					subord		= NULL;

	DNSServiceErrorType				err			= 0;

	HRESULT							hr			= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*service = NULL;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( regtype, regtypeUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );

	ok = BSTRToUTF8( domain, domainUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	subord = m_primary;

	err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service)

{

	CComObject<CDNSSDService>	*	object			= NULL;

	std::string						serviceNameUTF8;

	std::string						regTypeUTF8;

	std::string						domainUTF8;

	DNSServiceRef					subord			= NULL;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*service = NULL;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );

	ok = BSTRToUTF8( regType, regTypeUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );

	ok = BSTRToUTF8( domain, domainUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	subord = m_primary;

	err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service)

{

	CComObject<CDNSSDService>	*	object			= NULL;

	std::string						serviceNameUTF8;

	std::string						regTypeUTF8;

	std::string						domainUTF8;

	std::string						hostUTF8;

	const void					*	txtRecord		= NULL;

	uint16_t						txtLen			= 0;

	DNSServiceRef					subord			= NULL;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*service = NULL;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );

	ok = BSTRToUTF8( regType, regTypeUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );

	ok = BSTRToUTF8( domain, domainUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );

	ok = BSTRToUTF8( host, hostUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	if ( record )

	{

		CComObject< CTXTRecord > * realTXTRecord;



		realTXTRecord = ( CComObject< CTXTRecord >* ) record;



		txtRecord	= realTXTRecord->GetBytes();

		txtLen		= realTXTRecord->GetLen();

	}



	subord = m_primary;

	err = DNSServiceRegister( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, hostUTF8.c_str(), htons( port ), txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service)

{

	CComObject<CDNSSDService>	*	object			= NULL;

	DNSServiceRef					subord			= NULL;

	std::string						fullNameUTF8;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*service = NULL;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( fullname, fullNameUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	subord = m_primary;

	err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record)

{

	CComObject<CDNSSDRecord>	*	object			= NULL;

	DNSRecordRef					rref			= NULL;

	std::string						fullNameUTF8;

	std::vector< BYTE >				byteArray;

	const void					*	byteArrayPtr	= NULL;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*object = NULL;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( fullName, fullNameUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	// Convert the VARIANT

	ok = VariantToByteArray( &rdata, byteArray );

	require_action( ok, exit, err = kDNSServiceErr_Unknown );



	try

	{

		object = new CComObject<CDNSSDRecord>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	err = DNSServiceRegisterRecord( m_primary, &rref, flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl, &RegisterRecordReply, object );

	require_noerr( err, exit );



	object->SetServiceObject( this );

	object->SetRecordRef( rref );

	this->SetEventManager( eventManager );



	*record = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record)

{

	CComObject<CDNSSDRecord>	*	object			= NULL;

	DNSRecordRef					rref			= NULL;

	std::vector< BYTE >				byteArray;

	const void					*	byteArrayPtr	= NULL;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*object = NULL;



	// Convert the VARIANT

	ok = VariantToByteArray( &rdata, byteArray );

	require_action( ok, exit, err = kDNSServiceErr_Unknown );



	try

	{

		object = new CComObject<CDNSSDRecord>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );

	require_noerr( err, exit );



	object->SetServiceObject( this );

	object->SetRecordRef( rref );



	*record = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}



STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata)

{

	std::string						fullNameUTF8;

	std::vector< BYTE >				byteArray;

	const void					*	byteArrayPtr	= NULL;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( fullName, fullNameUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	// Convert the VARIANT

	ok = VariantToByteArray( &rdata, byteArray );

	require_action( ok, exit, err = kDNSServiceErr_Unknown );



	err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL );

	require_noerr( err, exit );



exit:



	return err;

}





STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value )

{

	std::string			propUTF8;

	std::vector< BYTE >	byteArray;

	SAFEARRAY		*	psa			= NULL;

	BYTE			*	pData		= NULL;

	uint32_t			elems		= 0;

	DNSServiceErrorType	err			= 0;

	BOOL				ok = TRUE;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( prop, propUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	// Setup the byte array

	require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );

	psa = V_ARRAY( value );

	require_action( psa, exit, err = kDNSServiceErr_Unknown );

	require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );

	byteArray.reserve( psa->rgsabound[0].cElements );

	byteArray.assign( byteArray.capacity(), 0 );

	elems = ( uint32_t ) byteArray.capacity();



	// Call the function and package the return value in the Variant

	err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );

	require_noerr( err, exit );

	ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );

	require_action( ok, exit, err = kDNSSDError_Unknown );



exit:



	if ( psa )

	{

		SafeArrayUnaccessData( psa );

		psa = NULL;

	}



	return err;

}



STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service)

{

	CComObject<CDNSSDService>	*	object			= NULL;

	DNSServiceRef					subord			= NULL;

	std::string						hostNameUTF8;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;

	BOOL							ok;



	check( m_primary );



	// Initialize

	*service = NULL;



	// Convert BSTR params to utf8

	ok = BSTRToUTF8( hostName, hostNameUTF8 );

	require_action( ok, exit, err = kDNSServiceErr_BadParam );



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	subord = m_primary;

	err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service)

{

	CComObject<CDNSSDService>	*	object			= NULL;

	DNSServiceRef					subord			= NULL;

	DNSServiceProtocol				prot			= 0;

	DNSServiceErrorType				err				= 0;

	HRESULT							hr				= 0;



	check( m_primary );



	// Initialize

	*service = NULL;



	try

	{

		object = new CComObject<CDNSSDService>();

	}

	catch ( ... )

	{

		object = NULL;

	}



	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );

	object->AddRef();



	prot = ( addressFamily | protocol );



	subord = m_primary;

	err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );

	require_noerr( err, exit );



	object->SetPrimaryRef( m_primary );

	object->SetSubordRef( subord );

	object->SetEventManager( eventManager );



	*service = object;



exit:



	if ( err && object )

	{

		object->Release();

	}



	return err;

}





STDMETHODIMP CDNSSDService::Stop(void)

{

	if ( !m_stopped )

	{

		m_stopped = TRUE;



		dlog( kDebugLevelTrace, "Stop()\n" );



		if ( m_isPrimary && m_primary )

		{

			SocketMap::iterator it;



			if ( m_hiddenWindow )

			{

				WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 );

			}



			it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) );



			if ( it != m_socketMap.end() )

			{

				m_socketMap.erase( it );

			}



			DNSServiceRefDeallocate( m_primary );

			m_primary = NULL;

		}

		else if ( m_subord )

		{

			DNSServiceRefDeallocate( m_subord );

			m_subord = NULL;

		}



		if ( m_eventManager != NULL )

		{

			m_eventManager->Release();

			m_eventManager = NULL;

		}

	}



	return S_OK;

}





void DNSSD_API
CDNSSDService::DomainEnumReply
    (
    DNSServiceRef                       sdRef,
    DNSServiceFlags                     flags,
    uint32_t                            ifIndex,
    DNSServiceErrorType                 errorCode,
    const char                          *replyDomainUTF8,
    void                                *context
    )

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		CComBSTR replyDomain;

		BOOL ok;

		

		ok = UTF8ToBSTR( replyDomainUTF8, replyDomain );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );



		if ( flags & kDNSServiceFlagsAdd )

		{

			eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );

		}

		else

		{

			eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );

		}

	}



exit:



	return;

}





void DNSSD_API
CDNSSDService::BrowseReply
		(
		DNSServiceRef                       sdRef,
		DNSServiceFlags                     flags,
		uint32_t                            ifIndex,
		DNSServiceErrorType                 errorCode,
		const char                          *serviceNameUTF8,
		const char                          *regTypeUTF8,
		const char                          *replyDomainUTF8,
		void                                *context
		)

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		CComBSTR	serviceName;

		CComBSTR	regType;

		CComBSTR	replyDomain;

	

		UTF8ToBSTR( serviceNameUTF8, serviceName );

		UTF8ToBSTR( regTypeUTF8, regType );

		UTF8ToBSTR( replyDomainUTF8, replyDomain );



		if ( flags & kDNSServiceFlagsAdd )

		{

			eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );

		}

		else

		{

			eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );

		}

	}



exit:



	return;

}





void DNSSD_API

CDNSSDService::ResolveReply

		(
		DNSServiceRef                       sdRef,
		DNSServiceFlags                     flags,
		uint32_t                            ifIndex,
		DNSServiceErrorType                 errorCode,
		const char                          *fullNameUTF8,
		const char                          *hostNameUTF8,
		uint16_t                            port,
		uint16_t                            txtLen,
		const unsigned char                 *txtRecord,
		void                                *context

		)

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		CComBSTR					fullName;

		CComBSTR					hostName;

		CComBSTR					regType;

		CComBSTR					replyDomain;

		CComObject< CTXTRecord >*	record;

		BOOL						ok;



		ok = UTF8ToBSTR( fullNameUTF8, fullName );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );

		ok = UTF8ToBSTR( hostNameUTF8, hostName );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );



		try

		{

			record = new CComObject<CTXTRecord>();

		}

		catch ( ... )

		{

			record = NULL;

		}



		require_action( record, exit, err = kDNSServiceErr_NoMemory );

		record->AddRef();



		if ( txtLen > 0 )

		{

			record->SetBytes( txtRecord, txtLen );

		}



		eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record );

	}



exit:



	return;

}





void DNSSD_API
CDNSSDService::RegisterReply
		(
		DNSServiceRef                       sdRef,
		DNSServiceFlags                     flags,
		DNSServiceErrorType                 errorCode,
		const char                          *serviceNameUTF8,
		const char                          *regTypeUTF8,
		const char                          *domainUTF8,
		void                                *context
		)

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		CComBSTR					serviceName;

		CComBSTR					regType;

		CComBSTR					domain;

		BOOL						ok;



		ok = UTF8ToBSTR( serviceNameUTF8, serviceName );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );

		ok = UTF8ToBSTR( regTypeUTF8, regType );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );

		ok = UTF8ToBSTR( domainUTF8, domain );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );



		eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );

	}



exit:



	return;

}





void DNSSD_API
CDNSSDService::QueryRecordReply
		(
		DNSServiceRef                       sdRef,
		DNSServiceFlags                     flags,
		uint32_t                            ifIndex,
		DNSServiceErrorType                 errorCode,
		const char                          *fullNameUTF8,
		uint16_t                            rrtype,
		uint16_t                            rrclass,
		uint16_t                            rdlen,
		const void                          *rdata,
		uint32_t                            ttl,
		void                                *context
		)

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		CComBSTR	fullName;

		VARIANT		var;

		BOOL		ok;



		ok = UTF8ToBSTR( fullNameUTF8, fullName );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );

		ok = ByteArrayToVariant( rdata, rdlen, &var );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );



		eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );

	}



exit:



	return;

}





void DNSSD_API
CDNSSDService::GetAddrInfoReply
		(
		DNSServiceRef                    sdRef,
		DNSServiceFlags                  flags,
		uint32_t                         ifIndex,
		DNSServiceErrorType              errorCode,
		const char                       *hostNameUTF8,
		const struct sockaddr            *rawAddress,
		uint32_t                         ttl,
		void                             *context
		)

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		CComBSTR			hostName;

		DWORD				sockaddrLen;

		DNSSDAddressFamily	addressFamily;

		char				addressUTF8[INET6_ADDRSTRLEN];

		DWORD				addressLen = sizeof( addressUTF8 );

		CComBSTR			address;

		BOOL				ok;



		ok = UTF8ToBSTR( hostNameUTF8, hostName );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );



		switch ( rawAddress->sa_family )

		{

			case AF_INET:

			{

				addressFamily	= kDNSSDAddressFamily_IPv4;

				sockaddrLen		= sizeof( sockaddr_in );

			}

			break;



			case AF_INET6:

			{

				addressFamily	= kDNSSDAddressFamily_IPv6;

				sockaddrLen		= sizeof( sockaddr_in6 );

			}

			break;

		}



		err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );

		require_noerr( err, exit );

		ok = UTF8ToBSTR( addressUTF8, address );

		require_action( ok, exit, err = kDNSServiceErr_Unknown );



		eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );

	}



exit:



	return;

}





void DNSSD_API
CDNSSDService::NATPortMappingReply
    (
    DNSServiceRef                    sdRef,
    DNSServiceFlags                  flags,
    uint32_t                         ifIndex,
    DNSServiceErrorType              errorCode,
    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
    DNSServiceProtocol               protocol,
    uint16_t                         internalPort,
    uint16_t                         externalPort,      /* may be different than the requested port     */
    uint32_t                         ttl,               /* may be different than the requested ttl      */
    void                             *context
    )

{

	CComObject<CDNSSDService>	* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	service = ( CComObject< CDNSSDService>* ) context;

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl  );

	}



exit:



	return;

}





void DNSSD_API
CDNSSDService::RegisterRecordReply
		(
		DNSServiceRef		sdRef,
		DNSRecordRef		RecordRef,
		DNSServiceFlags		flags,
		DNSServiceErrorType	errorCode,
		void				*context
		)

{

	CComObject<CDNSSDRecord>	* record		= NULL;

	CDNSSDService				* service		= NULL;

	CDNSSDEventManager			* eventManager	= NULL;

	int err = 0;

	

	record = ( CComObject< CDNSSDRecord >* ) context;

	require_action( record, exit, err = kDNSServiceErr_Unknown );

	service = record->GetServiceObject();

	require_action( service, exit, err = kDNSServiceErr_Unknown );



	if ( service->ShouldHandleReply( errorCode, eventManager ) )

	{

		eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags );

	}



exit:



	return;

}





BOOL

CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager )

{

	BOOL ok = FALSE;



	if ( !this->Stopped() )

	{

		eventManager = this->GetEventManager();

		require_action( eventManager, exit, ok = FALSE );



		if ( !errorCode )

		{

			ok = TRUE;

		}

		else

		{

			eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode );

		}

	}



exit:



	return ok;

}





LRESULT CALLBACK

CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )

{

	if ( msg == WM_SOCKET )

	{

		SocketMap::iterator it;

			

		it = m_socketMap.find( ( SOCKET ) wParam );

		check( it != m_socketMap.end() );



		if ( it != m_socketMap.end() )

		{

			DNSServiceProcessResult( it->second->m_primary );

		}

	}



	return DefWindowProc(hWnd, msg, wParam, lParam);;

}

