diff options
Diffstat (limited to 'mDNSResponder/Clients/BonjourExample/BonjourExample.cpp')
-rw-r--r-- | mDNSResponder/Clients/BonjourExample/BonjourExample.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/mDNSResponder/Clients/BonjourExample/BonjourExample.cpp b/mDNSResponder/Clients/BonjourExample/BonjourExample.cpp new file mode 100644 index 00000000..f517456c --- /dev/null +++ b/mDNSResponder/Clients/BonjourExample/BonjourExample.cpp @@ -0,0 +1,199 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2005 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. + */ + +#include "stdafx.h" + +#include <assert.h> +#include <stdio.h> + +#include "dns_sd.h" + +// Constants + +#define BONJOUR_EVENT ( WM_USER + 0x100 ) // Message sent to the Window when a Bonjour event occurs. + +// Prototypes + +static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam ); + +static void DNSSD_API + BrowserCallBack( + DNSServiceRef inServiceRef, + DNSServiceFlags inFlags, + uint32_t inIFI, + DNSServiceErrorType inError, + const char * inName, + const char * inType, + const char * inDomain, + void * inContext ); + +// Globals + +DNSServiceRef gServiceRef = NULL; + +// Main entry point for application. + +int _tmain( int argc, _TCHAR *argv[] ) +{ + HINSTANCE instance; + WNDCLASSEX wcex; + HWND wind; + MSG msg; + DNSServiceErrorType err; + + (void) argc; // Unused + (void) argv; // Unused + + // Create the window. This window won't actually be shown, but it demonstrates how to use Bonjour + // with Windows GUI applications by having Bonjour events processed as messages to a Window. + + instance = GetModuleHandle( NULL ); + assert( instance ); + + wcex.cbSize = sizeof( wcex ); + wcex.style = 0; + wcex.lpfnWndProc = (WNDPROC) WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = instance; + wcex.hIcon = NULL; + wcex.hCursor = NULL; + wcex.hbrBackground = NULL; + wcex.lpszMenuName = NULL; + wcex.lpszClassName = TEXT( "BonjourExample" ); + wcex.hIconSm = NULL; + RegisterClassEx( &wcex ); + + wind = CreateWindow( wcex.lpszClassName, wcex.lpszClassName, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, + 0, NULL, NULL, instance, NULL ); + assert( wind ); + + // Start browsing for services and associate the Bonjour browser with our window using the + // WSAAsyncSelect mechanism. Whenever something related to the Bonjour browser occurs, our + // private Windows message will be sent to our window so we can give Bonjour a chance to + // process it. This allows Bonjour to avoid using a secondary thread (and all the issues + // with synchronization that would introduce), but still process everything asynchronously. + // This also simplifies app code because Bonjour will only run when we explicitly call it. + + err = DNSServiceBrowse( + &gServiceRef, // Receives reference to Bonjour browser object. + 0, // No flags. + kDNSServiceInterfaceIndexAny, // Browse on all network interfaces. + "_http._tcp", // Browse for HTTP service types. + NULL, // Browse on the default domain (e.g. local.). + BrowserCallBack, // Callback function when Bonjour events occur. + NULL ); // No callback context needed. + assert( err == kDNSServiceErr_NoError ); + + err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, FD_READ | FD_CLOSE ); + assert( err == kDNSServiceErr_NoError ); + + fprintf( stderr, "Browsing for _http._tcp\n" ); + + // Main event loop for the application. All Bonjour events are dispatched while in this loop. + + while( GetMessage( &msg, NULL, 0, 0 ) ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + + // Clean up Bonjour. This is not strictly necessary since the normal process cleanup will + // close Bonjour socket(s) and release memory, but it's here to demonstrate how to do it. + + if( gServiceRef ) + { + WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, 0 ); + DNSServiceRefDeallocate( gServiceRef ); + } + return( 0 ); +} + +// Callback for the Window. Bonjour events are delivered here. + +static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam ) +{ + LRESULT result; + DNSServiceErrorType err; + + switch( inMsg ) + { + case BONJOUR_EVENT: + + // Process the Bonjour event. All Bonjour callbacks occur from within this function. + // If an error occurs while trying to process the result, it most likely means that + // something serious has gone wrong with Bonjour, such as it being terminated. This + // does not normally occur, but code should be prepared to handle it. If the error + // is ignored, the window will receive a constant stream of BONJOUR_EVENT messages so + // if an error occurs, we disassociate the DNSServiceRef from the window, deallocate + // it, and invalidate the reference so we don't try to deallocate it again on quit. + // Since this is a simple example app, if this error occurs, we quit the app too. + + err = DNSServiceProcessResult( gServiceRef ); + if( err != kDNSServiceErr_NoError ) + { + fprintf( stderr, "### ERROR! serious Bonjour error: %d\n", err ); + + WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), inWindow, BONJOUR_EVENT, 0 ); + DNSServiceRefDeallocate( gServiceRef ); + gServiceRef = NULL; + + PostQuitMessage( 0 ); + } + result = 0; + break; + + default: + result = DefWindowProc( inWindow, inMsg, inWParam, inLParam ); + break; + } + return( result ); +} + +// Callback for Bonjour browser events. Called when services are added or removed. + +static void DNSSD_API + BrowserCallBack( + DNSServiceRef inServiceRef, + DNSServiceFlags inFlags, + uint32_t inIFI, + DNSServiceErrorType inError, + const char * inName, + const char * inType, + const char * inDomain, + void * inContext ) +{ + (void) inServiceRef; // Unused + (void) inContext; // Unused + + if( inError == kDNSServiceErr_NoError ) + { + const char * action; + const char * more; + + if( inFlags & kDNSServiceFlagsAdd ) action = "ADD"; + else action = "RMV"; + if( inFlags & kDNSServiceFlagsMoreComing ) more = " (MORE)"; + else more = ""; + + fprintf( stderr, "%s %30s.%s%s on interface %d%s\n", action, inName, inType, inDomain, (int) inIFI, more ); + } + else + { + fprintf( stderr, "Bonjour browser error occurred: %d\n", inError ); + } +} |