]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/BonjourExample/BonjourExample.cpp
mDNSResponder-258.13.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
18 #include "stdafx.h"
19
20 #include <assert.h>
21 #include <stdio.h>
22
23 #include "dns_sd.h"
24
25 // Constants
26
27 #define BONJOUR_EVENT ( WM_USER + 0x100 ) // Message sent to the Window when a Bonjour event occurs.
28
29 // Prototypes
30
31 static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam );
32
33 static void DNSSD_API
34 BrowserCallBack(
35 DNSServiceRef inServiceRef,
36 DNSServiceFlags inFlags,
37 uint32_t inIFI,
38 DNSServiceErrorType inError,
39 const char * inName,
40 const char * inType,
41 const char * inDomain,
42 void * inContext );
43
44 // Globals
45
46 DNSServiceRef gServiceRef = NULL;
47
48 // Main entry point for application.
49
50 int _tmain( int argc, _TCHAR *argv[] )
51 {
52 HINSTANCE instance;
53 WNDCLASSEX wcex;
54 HWND wind;
55 MSG msg;
56 DNSServiceErrorType err;
57
58 (void) argc; // Unused
59 (void) argv; // Unused
60
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.
63
64 instance = GetModuleHandle( NULL );
65 assert( instance );
66
67 wcex.cbSize = sizeof( wcex );
68 wcex.style = 0;
69 wcex.lpfnWndProc = (WNDPROC) WndProc;
70 wcex.cbClsExtra = 0;
71 wcex.cbWndExtra = 0;
72 wcex.hInstance = instance;
73 wcex.hIcon = NULL;
74 wcex.hCursor = NULL;
75 wcex.hbrBackground = NULL;
76 wcex.lpszMenuName = NULL;
77 wcex.lpszClassName = TEXT( "BonjourExample" );
78 wcex.hIconSm = NULL;
79 RegisterClassEx( &wcex );
80
81 wind = CreateWindow( wcex.lpszClassName, wcex.lpszClassName, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT,
82 0, NULL, NULL, instance, NULL );
83 assert( wind );
84
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.
91
92 err = DNSServiceBrowse(
93 &gServiceRef, // Receives reference to Bonjour browser object.
94 0, // No flags.
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 );
101
102 err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, FD_READ | FD_CLOSE );
103 assert( err == kDNSServiceErr_NoError );
104
105 fprintf( stderr, "Browsing for _http._tcp\n" );
106
107 // Main event loop for the application. All Bonjour events are dispatched while in this loop.
108
109 while( GetMessage( &msg, NULL, 0, 0 ) )
110 {
111 TranslateMessage( &msg );
112 DispatchMessage( &msg );
113 }
114
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.
117
118 if( gServiceRef )
119 {
120 WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, 0 );
121 DNSServiceRefDeallocate( gServiceRef );
122 }
123 return( 0 );
124 }
125
126 // Callback for the Window. Bonjour events are delivered here.
127
128 static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam )
129 {
130 LRESULT result;
131 DNSServiceErrorType err;
132
133 switch( inMsg )
134 {
135 case BONJOUR_EVENT:
136
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.
145
146 err = DNSServiceProcessResult( gServiceRef );
147 if( err != kDNSServiceErr_NoError )
148 {
149 fprintf( stderr, "### ERROR! serious Bonjour error: %d\n", err );
150
151 WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), inWindow, BONJOUR_EVENT, 0 );
152 DNSServiceRefDeallocate( gServiceRef );
153 gServiceRef = NULL;
154
155 PostQuitMessage( 0 );
156 }
157 result = 0;
158 break;
159
160 default:
161 result = DefWindowProc( inWindow, inMsg, inWParam, inLParam );
162 break;
163 }
164 return( result );
165 }
166
167 // Callback for Bonjour browser events. Called when services are added or removed.
168
169 static void DNSSD_API
170 BrowserCallBack(
171 DNSServiceRef inServiceRef,
172 DNSServiceFlags inFlags,
173 uint32_t inIFI,
174 DNSServiceErrorType inError,
175 const char * inName,
176 const char * inType,
177 const char * inDomain,
178 void * inContext )
179 {
180 (void) inServiceRef; // Unused
181 (void) inContext; // Unused
182
183 if( inError == kDNSServiceErr_NoError )
184 {
185 const char * action;
186 const char * more;
187
188 if( inFlags & kDNSServiceFlagsAdd ) action = "ADD";
189 else action = "RMV";
190 if( inFlags & kDNSServiceFlagsMoreComing ) more = " (MORE)";
191 else more = "";
192
193 fprintf( stderr, "%s %30s.%s%s on interface %d%s\n", action, inName, inType, inDomain, (int) inIFI, more );
194 }
195 else
196 {
197 fprintf( stderr, "Bonjour browser error occurred: %d\n", inError );
198 }
199 }