]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/BonjourExample/BonjourExample.cpp
mDNSResponder-108.tar.gz
[apple/mdnsresponder.git] / Clients / BonjourExample / BonjourExample.cpp
1 /*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: BonjourExample.cpp,v $
26 Revision 1.1 2005/05/20 22:01:01 bradley
27 Bonjour for Windows example code to browse for HTTP services and deliver via Window messages.
28
29 */
30
31 #include "stdafx.h"
32
33 #include <assert.h>
34 #include <stdio.h>
35
36 #include "dns_sd.h"
37
38 // Constants
39
40 #define BONJOUR_EVENT ( WM_USER + 0x100 ) // Message sent to the Window when a Bonjour event occurs.
41
42 // Prototypes
43
44 static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam );
45
46 static void DNSSD_API
47 BrowserCallBack(
48 DNSServiceRef inServiceRef,
49 DNSServiceFlags inFlags,
50 uint32_t inIFI,
51 DNSServiceErrorType inError,
52 const char * inName,
53 const char * inType,
54 const char * inDomain,
55 void * inContext );
56
57 // Globals
58
59 DNSServiceRef gServiceRef = NULL;
60
61 // Main entry point for application.
62
63 int _tmain( int argc, _TCHAR *argv[] )
64 {
65 HINSTANCE instance;
66 WNDCLASSEX wcex;
67 HWND wind;
68 MSG msg;
69 DNSServiceErrorType err;
70
71 (void) argc; // Unused
72 (void) argv; // Unused
73
74 // Create the window. This window won't actually be shown, but it demonstrates how to use Bonjour
75 // with Windows GUI applications by having Bonjour events processed as messages to a Window.
76
77 instance = GetModuleHandle( NULL );
78 assert( instance );
79
80 wcex.cbSize = sizeof( wcex );
81 wcex.style = 0;
82 wcex.lpfnWndProc = (WNDPROC) WndProc;
83 wcex.cbClsExtra = 0;
84 wcex.cbWndExtra = 0;
85 wcex.hInstance = instance;
86 wcex.hIcon = NULL;
87 wcex.hCursor = NULL;
88 wcex.hbrBackground = NULL;
89 wcex.lpszMenuName = NULL;
90 wcex.lpszClassName = TEXT( "BonjourExample" );
91 wcex.hIconSm = NULL;
92 RegisterClassEx( &wcex );
93
94 wind = CreateWindow( wcex.lpszClassName, wcex.lpszClassName, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT,
95 0, NULL, NULL, instance, NULL );
96 assert( wind );
97
98 // Start browsing for services and associate the Bonjour browser with our window using the
99 // WSAAsyncSelect mechanism. Whenever something related to the Bonjour browser occurs, our
100 // private Windows message will be sent to our window so we can give Bonjour a chance to
101 // process it. This allows Bonjour to avoid using a secondary thread (and all the issues
102 // with synchronization that would introduce), but still process everything asynchronously.
103 // This also simplifies app code because Bonjour will only run when we explicitly call it.
104
105 err = DNSServiceBrowse(
106 &gServiceRef, // Receives reference to Bonjour browser object.
107 0, // No flags.
108 kDNSServiceInterfaceIndexAny, // Browse on all network interfaces.
109 "_http._tcp", // Browse for HTTP service types.
110 NULL, // Browse on the default domain (e.g. local.).
111 BrowserCallBack, // Callback function when Bonjour events occur.
112 NULL ); // No callback context needed.
113 assert( err == kDNSServiceErr_NoError );
114
115 err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, FD_READ | FD_CLOSE );
116 assert( err == kDNSServiceErr_NoError );
117
118 fprintf( stderr, "Browsing for _http._tcp\n" );
119
120 // Main event loop for the application. All Bonjour events are dispatched while in this loop.
121
122 while( GetMessage( &msg, NULL, 0, 0 ) )
123 {
124 TranslateMessage( &msg );
125 DispatchMessage( &msg );
126 }
127
128 // Clean up Bonjour. This is not strictly necessary since the normal process cleanup will
129 // close Bonjour socket(s) and release memory, but it's here to demonstrate how to do it.
130
131 if( gServiceRef )
132 {
133 WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, 0 );
134 DNSServiceRefDeallocate( gServiceRef );
135 }
136 return( 0 );
137 }
138
139 // Callback for the Window. Bonjour events are delivered here.
140
141 static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam )
142 {
143 LRESULT result;
144 DNSServiceErrorType err;
145
146 switch( inMsg )
147 {
148 case BONJOUR_EVENT:
149
150 // Process the Bonjour event. All Bonjour callbacks occur from within this function.
151 // If an error occurs while trying to process the result, it most likely means that
152 // something serious has gone wrong with Bonjour, such as it being terminated. This
153 // does not normally occur, but code should be prepared to handle it. If the error
154 // is ignored, the window will receive a constant stream of BONJOUR_EVENT messages so
155 // if an error occurs, we disassociate the DNSServiceRef from the window, deallocate
156 // it, and invalidate the reference so we don't try to deallocate it again on quit.
157 // Since this is a simple example app, if this error occurs, we quit the app too.
158
159 err = DNSServiceProcessResult( gServiceRef );
160 if( err != kDNSServiceErr_NoError )
161 {
162 fprintf( stderr, "### ERROR! serious Bonjour error: %d\n", err );
163
164 WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), inWindow, BONJOUR_EVENT, 0 );
165 DNSServiceRefDeallocate( gServiceRef );
166 gServiceRef = NULL;
167
168 PostQuitMessage( 0 );
169 }
170 result = 0;
171 break;
172
173 default:
174 result = DefWindowProc( inWindow, inMsg, inWParam, inLParam );
175 break;
176 }
177 return( result );
178 }
179
180 // Callback for Bonjour browser events. Called when services are added or removed.
181
182 static void DNSSD_API
183 BrowserCallBack(
184 DNSServiceRef inServiceRef,
185 DNSServiceFlags inFlags,
186 uint32_t inIFI,
187 DNSServiceErrorType inError,
188 const char * inName,
189 const char * inType,
190 const char * inDomain,
191 void * inContext )
192 {
193 (void) inServiceRef; // Unused
194 (void) inContext; // Unused
195
196 if( inError == kDNSServiceErr_NoError )
197 {
198 const char * action;
199 const char * more;
200
201 if( inFlags & kDNSServiceFlagsAdd ) action = "ADD";
202 else action = "RMV";
203 if( inFlags & kDNSServiceFlagsMoreComing ) more = " (MORE)";
204 else more = "";
205
206 fprintf( stderr, "%s %30s.%s%s on interface %d%s\n", action, inName, inType, inDomain, (int) inIFI, more );
207 }
208 else
209 {
210 fprintf( stderr, "Bonjour browser error occurred: %d\n", inError );
211 }
212 }