2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
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.
40 #define BONJOUR_EVENT ( WM_USER + 0x100 ) // Message sent to the Window when a Bonjour event occurs.
44 static LRESULT CALLBACK
WndProc( HWND inWindow
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
);
48 DNSServiceRef inServiceRef
,
49 DNSServiceFlags inFlags
,
51 DNSServiceErrorType inError
,
54 const char * inDomain
,
59 DNSServiceRef gServiceRef
= NULL
;
61 // Main entry point for application.
63 int _tmain( int argc
, _TCHAR
*argv
[] )
69 DNSServiceErrorType err
;
71 (void) argc
; // Unused
72 (void) argv
; // Unused
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.
77 instance
= GetModuleHandle( NULL
);
80 wcex
.cbSize
= sizeof( wcex
);
82 wcex
.lpfnWndProc
= (WNDPROC
) WndProc
;
85 wcex
.hInstance
= instance
;
88 wcex
.hbrBackground
= NULL
;
89 wcex
.lpszMenuName
= NULL
;
90 wcex
.lpszClassName
= TEXT( "BonjourExample" );
92 RegisterClassEx( &wcex
);
94 wind
= CreateWindow( wcex
.lpszClassName
, wcex
.lpszClassName
, 0, CW_USEDEFAULT
, 0, CW_USEDEFAULT
,
95 0, NULL
, NULL
, instance
, NULL
);
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.
105 err
= DNSServiceBrowse(
106 &gServiceRef
, // Receives reference to Bonjour browser object.
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
);
115 err
= WSAAsyncSelect( (SOCKET
) DNSServiceRefSockFD( gServiceRef
), wind
, BONJOUR_EVENT
, FD_READ
| FD_CLOSE
);
116 assert( err
== kDNSServiceErr_NoError
);
118 fprintf( stderr
, "Browsing for _http._tcp\n" );
120 // Main event loop for the application. All Bonjour events are dispatched while in this loop.
122 while( GetMessage( &msg
, NULL
, 0, 0 ) )
124 TranslateMessage( &msg
);
125 DispatchMessage( &msg
);
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.
133 WSAAsyncSelect( (SOCKET
) DNSServiceRefSockFD( gServiceRef
), wind
, BONJOUR_EVENT
, 0 );
134 DNSServiceRefDeallocate( gServiceRef
);
139 // Callback for the Window. Bonjour events are delivered here.
141 static LRESULT CALLBACK
WndProc( HWND inWindow
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
)
144 DNSServiceErrorType err
;
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.
159 err
= DNSServiceProcessResult( gServiceRef
);
160 if( err
!= kDNSServiceErr_NoError
)
162 fprintf( stderr
, "### ERROR! serious Bonjour error: %d\n", err
);
164 WSAAsyncSelect( (SOCKET
) DNSServiceRefSockFD( gServiceRef
), inWindow
, BONJOUR_EVENT
, 0 );
165 DNSServiceRefDeallocate( gServiceRef
);
168 PostQuitMessage( 0 );
174 result
= DefWindowProc( inWindow
, inMsg
, inWParam
, inLParam
);
180 // Callback for Bonjour browser events. Called when services are added or removed.
182 static void DNSSD_API
184 DNSServiceRef inServiceRef
,
185 DNSServiceFlags inFlags
,
187 DNSServiceErrorType inError
,
190 const char * inDomain
,
193 (void) inServiceRef
; // Unused
194 (void) inContext
; // Unused
196 if( inError
== kDNSServiceErr_NoError
)
201 if( inFlags
& kDNSServiceFlagsAdd
) action
= "ADD";
203 if( inFlags
& kDNSServiceFlagsMoreComing
) more
= " (MORE)";
206 fprintf( stderr
, "%s %30s.%s%s on interface %d%s\n", action
, inName
, inType
, inDomain
, (int) inIFI
, more
);
210 fprintf( stderr
, "Bonjour browser error occurred: %d\n", inError
);