summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSWindows/DLLX/DNSSDService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSWindows/DLLX/DNSSDService.cpp')
-rwxr-xr-xmDNSResponder/mDNSWindows/DLLX/DNSSDService.cpp2095
1 files changed, 2095 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSWindows/DLLX/DNSSDService.cpp b/mDNSResponder/mDNSWindows/DLLX/DNSSDService.cpp
new file mode 100755
index 00000000..b8ce49be
--- /dev/null
+++ b/mDNSResponder/mDNSWindows/DLLX/DNSSDService.cpp
@@ -0,0 +1,2095 @@
+/* -*- 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);;
+
+}
+