1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
27 #define BONJOUR_EVENT ( WM_USER + 0x100 ) // Message sent to the Window when a Bonjour event occurs.
31 static LRESULT CALLBACK
WndProc( HWND inWindow
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
);
35 DNSServiceRef inServiceRef
,
36 DNSServiceFlags inFlags
,
38 DNSServiceErrorType inError
,
41 const char * inDomain
,
46 DNSServiceRef gServiceRef
= NULL
;
48 // Main entry point for application.
50 int _tmain( int argc
, _TCHAR
*argv
[] )
56 DNSServiceErrorType err
;
58 (void) argc
; // Unused
59 (void) argv
; // Unused
61 // Create the window. This window won't actually be shown, but it demonstrates how to use Bonjour
62 // with Windows GUI applications by having Bonjour events processed as messages to a Window.
64 instance
= GetModuleHandle( NULL
);
67 wcex
.cbSize
= sizeof( wcex
);
69 wcex
.lpfnWndProc
= (WNDPROC
) WndProc
;
72 wcex
.hInstance
= instance
;
75 wcex
.hbrBackground
= NULL
;
76 wcex
.lpszMenuName
= NULL
;
77 wcex
.lpszClassName
= TEXT( "BonjourExample" );
79 RegisterClassEx( &wcex
);
81 wind
= CreateWindow( wcex
.lpszClassName
, wcex
.lpszClassName
, 0, CW_USEDEFAULT
, 0, CW_USEDEFAULT
,
82 0, NULL
, NULL
, instance
, NULL
);
85 // Start browsing for services and associate the Bonjour browser with our window using the
86 // WSAAsyncSelect mechanism. Whenever something related to the Bonjour browser occurs, our
87 // private Windows message will be sent to our window so we can give Bonjour a chance to
88 // process it. This allows Bonjour to avoid using a secondary thread (and all the issues
89 // with synchronization that would introduce), but still process everything asynchronously.
90 // This also simplifies app code because Bonjour will only run when we explicitly call it.
92 err
= DNSServiceBrowse(
93 &gServiceRef
, // Receives reference to Bonjour browser object.
95 kDNSServiceInterfaceIndexAny
, // Browse on all network interfaces.
96 "_http._tcp", // Browse for HTTP service types.
97 NULL
, // Browse on the default domain (e.g. local.).
98 BrowserCallBack
, // Callback function when Bonjour events occur.
99 NULL
); // No callback context needed.
100 assert( err
== kDNSServiceErr_NoError
);
102 err
= WSAAsyncSelect( (SOCKET
) DNSServiceRefSockFD( gServiceRef
), wind
, BONJOUR_EVENT
, FD_READ
| FD_CLOSE
);
103 assert( err
== kDNSServiceErr_NoError
);
105 fprintf( stderr
, "Browsing for _http._tcp\n" );
107 // Main event loop for the application. All Bonjour events are dispatched while in this loop.
109 while( GetMessage( &msg
, NULL
, 0, 0 ) )
111 TranslateMessage( &msg
);
112 DispatchMessage( &msg
);
115 // Clean up Bonjour. This is not strictly necessary since the normal process cleanup will
116 // close Bonjour socket(s) and release memory, but it's here to demonstrate how to do it.
120 WSAAsyncSelect( (SOCKET
) DNSServiceRefSockFD( gServiceRef
), wind
, BONJOUR_EVENT
, 0 );
121 DNSServiceRefDeallocate( gServiceRef
);
126 // Callback for the Window. Bonjour events are delivered here.
128 static LRESULT CALLBACK
WndProc( HWND inWindow
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
)
131 DNSServiceErrorType err
;
137 // Process the Bonjour event. All Bonjour callbacks occur from within this function.
138 // If an error occurs while trying to process the result, it most likely means that
139 // something serious has gone wrong with Bonjour, such as it being terminated. This
140 // does not normally occur, but code should be prepared to handle it. If the error
141 // is ignored, the window will receive a constant stream of BONJOUR_EVENT messages so
142 // if an error occurs, we disassociate the DNSServiceRef from the window, deallocate
143 // it, and invalidate the reference so we don't try to deallocate it again on quit.
144 // Since this is a simple example app, if this error occurs, we quit the app too.
146 err
= DNSServiceProcessResult( gServiceRef
);
147 if( err
!= kDNSServiceErr_NoError
)
149 fprintf( stderr
, "### ERROR! serious Bonjour error: %d\n", err
);
151 WSAAsyncSelect( (SOCKET
) DNSServiceRefSockFD( gServiceRef
), inWindow
, BONJOUR_EVENT
, 0 );
152 DNSServiceRefDeallocate( gServiceRef
);
155 PostQuitMessage( 0 );
161 result
= DefWindowProc( inWindow
, inMsg
, inWParam
, inLParam
);
167 // Callback for Bonjour browser events. Called when services are added or removed.
169 static void DNSSD_API
171 DNSServiceRef inServiceRef
,
172 DNSServiceFlags inFlags
,
174 DNSServiceErrorType inError
,
177 const char * inDomain
,
180 (void) inServiceRef
; // Unused
181 (void) inContext
; // Unused
183 if( inError
== kDNSServiceErr_NoError
)
188 if( inFlags
& kDNSServiceFlagsAdd
) action
= "ADD";
190 if( inFlags
& kDNSServiceFlagsMoreComing
) more
= " (MORE)";
193 fprintf( stderr
, "%s %30s.%s%s on interface %d%s\n", action
, inName
, inType
, inDomain
, (int) inIFI
, more
);
197 fprintf( stderr
, "Bonjour browser error occurred: %d\n", inError
);