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