]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/RMxServer.c
3c2808925a8334e902d2b997d7a8afc60bc8b299
[apple/mdnsresponder.git] / mDNSWindows / RMxServer.c
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: RMxServer.c,v $
28 Revision 1.6 2004/04/15 01:00:05 bradley
29 Removed support for automatically querying for A/AAAA records when resolving names. Platforms
30 without .local name resolving support will need to manually query for A/AAAA records as needed.
31
32 Revision 1.5 2004/04/09 21:03:14 bradley
33 Changed port numbers to use network byte order for consistency with other platforms.
34
35 Revision 1.4 2004/04/08 21:14:19 bradley
36 Changed resolve callback to use correct calling conventions (previously hidden by a cast).
37
38 Revision 1.3 2004/04/08 09:43:43 bradley
39 Changed callback calling conventions to __stdcall so they can be used with C# delegates.
40
41 Revision 1.2 2004/03/16 22:09:03 bradley
42 Skip socket creation failures to handle local IPv6 addresses being returned by Windows even when
43 they are not actually supported by the OS; Log a message and only fail if no sockets can be created.
44
45 Revision 1.1 2004/01/30 02:35:13 bradley
46 Rendezvous Message Exchange implementation for DNS-SD IPC on Windows.
47
48 */
49
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53
54 #include "CommonServices.h"
55 #include "DebugServices.h"
56
57 #include "DNSSD.h"
58 #include "DNSSDDirect.h"
59 #include "RMxCommon.h"
60
61 #include "RMxServer.h"
62
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66
67 #if 0
68 #pragma mark == Constants ==
69 #endif
70
71 //===========================================================================================================================
72 // Constants
73 //===========================================================================================================================
74
75 #define DEBUG_NAME "[RMxServer] "
76
77 #if 0
78 #pragma mark == Structures ==
79 #endif
80
81 //===========================================================================================================================
82 // Structures
83 //===========================================================================================================================
84
85 typedef void ( *DNSServiceRefReleaseCallBack )( DNSServiceRef inRef );
86
87 // DNSServiceRef
88
89 typedef struct _DNSServiceRef_t _DNSServiceRef_t;
90 struct _DNSServiceRef_t
91 {
92 RMxOpCode opcode;
93 bool sessionClosing;
94 RMxSessionRef session;
95 DNSServiceRef directObj;
96 DNSRecordRef records;
97 };
98
99 // DNSRecordRef
100
101 typedef struct _DNSRecordRef_t _DNSRecordRef_t;
102 struct _DNSRecordRef_t
103 {
104 DNSRecordRef next;
105 uint32_t id;
106 DNSServiceRef owner;
107 DNSRecordRef directObj;
108 };
109
110 #if 0
111 #pragma mark == Prototypes ==
112 #endif
113
114 //===========================================================================================================================
115 // Prototypes
116 //===========================================================================================================================
117
118 // RMx
119
120 DEBUG_LOCAL OSStatus RMxServerRunInitialize( void );
121 DEBUG_LOCAL void RMxServerRunFinalize( void );
122 DEBUG_LOCAL void RMxServerMessageCallBack( RMxMessage *inMessage );
123
124 // General
125
126 DEBUG_LOCAL void DNSServiceRefDeallocate_server( DNSServiceRef inRef );
127 DEBUG_LOCAL void DNSServiceCheckVersion_server( RMxMessage *inMessage );
128
129 // Properties
130
131 DEBUG_LOCAL void DNSServiceCopyProperty_server( RMxMessage *inMessage );
132 DEBUG_LOCAL OSStatus DNSServiceCopyPropertySendData_server( DNSPropertyCode inCode, RMxMessage *inMessage );
133
134 // Domain Enumeration
135
136 DEBUG_LOCAL void DNSServiceEnumerateDomains_server( RMxMessage *inMessage );
137 DEBUG_LOCAL void CALLBACK_COMPAT
138 DNSServiceEnumerateDomainsCallBack_server(
139 DNSServiceRef sdRef,
140 DNSServiceFlags flags,
141 uint32_t interfaceIndex,
142 DNSServiceErrorType errorCode,
143 const char * replyDomain,
144 void * context );
145
146 // Service Registration
147
148 DEBUG_LOCAL void DNSServiceRegister_server( RMxMessage *inMessage );
149 DEBUG_LOCAL void CALLBACK_COMPAT
150 DNSServiceRegisterCallBack_server(
151 DNSServiceRef inRef,
152 DNSServiceFlags inFlags,
153 DNSServiceErrorType inErrorCode,
154 const char * inName,
155 const char * inType,
156 const char * inDomain,
157 void * inContext );
158
159 DEBUG_LOCAL void DNSServiceAddRecord_server( RMxMessage *inMessage );
160 DEBUG_LOCAL void DNSServiceUpdateRecord_server( RMxMessage *inMessage );
161 DEBUG_LOCAL void DNSServiceRemoveRecord_server( RMxMessage *inMessage );
162
163 // Service Discovery
164
165 DEBUG_LOCAL void DNSServiceBrowse_server( RMxMessage *inMessage );
166 DEBUG_LOCAL void CALLBACK_COMPAT
167 DNSServiceBrowseCallBack_server(
168 DNSServiceRef inRef,
169 DNSServiceFlags inFlags,
170 uint32_t inInterfaceIndex,
171 DNSServiceErrorType inErrorCode,
172 const char * inName,
173 const char * inType,
174 const char * inDomain,
175 void * inContext );
176
177 DEBUG_LOCAL void DNSServiceResolve_server( RMxMessage *inMessage );
178 DEBUG_LOCAL void CALLBACK_COMPAT
179 DNSServiceResolveCallBack_server(
180 DNSServiceRef inRef,
181 DNSServiceFlags inFlags,
182 uint32_t inInterfaceIndex,
183 DNSServiceErrorType inErrorCode,
184 const char * inFullName,
185 const char * inHostName,
186 uint16_t inPort,
187 uint16_t inTXTSize,
188 const char * inTXT,
189 void * inContext );
190
191 // Special Purpose
192
193 DEBUG_LOCAL void DNSServiceCreateConnection_server( RMxMessage *inMessage );
194
195 DEBUG_LOCAL void DNSServiceRegisterRecord_server( RMxMessage *inMessage );
196 DEBUG_LOCAL void CALLBACK_COMPAT
197 DNSServiceRegisterRecordCallBack_server(
198 DNSServiceRef inRef,
199 DNSRecordRef inRecordRef,
200 DNSServiceFlags inFlags,
201 DNSServiceErrorType inErrorCode,
202 void * inContext );
203
204 DEBUG_LOCAL void DNSServiceQueryRecord_server( RMxMessage *inMessage );
205 DEBUG_LOCAL void CALLBACK_COMPAT
206 DNSServiceQueryRecordCallBack_server(
207 DNSServiceRef inRef,
208 DNSServiceFlags inFlags,
209 uint32_t inInterfaceIndex,
210 DNSServiceErrorType inErrorCode,
211 const char * inName,
212 uint16_t inRRType,
213 uint16_t inRRClass,
214 uint16_t inRDataSize,
215 const void * inRData,
216 uint32_t inTTL,
217 void * inContext );
218
219 DEBUG_LOCAL void DNSServiceReconfirmRecord_server( RMxMessage *inMessage );
220
221 #if 0
222 #pragma mark == Globals ==
223 #endif
224
225 //===========================================================================================================================
226 // Globals
227 //===========================================================================================================================
228
229 DEBUG_LOCAL RMxServerFlags gRMxServerFlags = kRMxServerFlagsNone;
230 DEBUG_LOCAL SocketRef gRMxServerSockets[ 2 ] = { kInvalidSocketRef, kInvalidSocketRef };
231 DEBUG_LOCAL HANDLE gRMxServerSocketEvents[ 2 ] = { NULL, NULL };
232 DEBUG_LOCAL HANDLE gRMxServerQuitDoneEvent = NULL;
233
234 #if 0
235 #pragma mark -
236 #pragma mark == RMx ==
237 #endif
238
239 //===========================================================================================================================
240 // RMxServerInitialize
241 //===========================================================================================================================
242
243 OSStatus RMxServerInitialize( RMxServerFlags inFlags )
244 {
245 OSStatus err;
246
247 err = RMxInitialize();
248 require_noerr( err, exit );
249
250 // Set up the quit done event to allow for waiting until the run loop is quit. A manual-reset event is used so
251 // multiple calls to the stopping code will all see that the quit event has been signaled (not just the first).
252 // The event is also created as signaled so even if run is not called, a stop or finalize will still run successfully.
253 // The event will be explicitly reset to an unsignaled state when the run loop starts.
254
255 gRMxServerQuitDoneEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
256 err = translate_errno( gRMxServerQuitDoneEvent, errno_compat(), kNoResourcesErr );
257 require_noerr( err, exit );
258
259 gRMxServerFlags = inFlags;
260
261 exit:
262 return( err );
263 }
264
265 //===========================================================================================================================
266 // RMxServerFinalize
267 //===========================================================================================================================
268
269 void RMxServerFinalize( void )
270 {
271 BOOL ok;
272
273 RMxServerStop( kRMxServerStopFlagsNone );
274
275 // Release the quit event.
276
277 if( gRMxServerQuitDoneEvent )
278 {
279 ok = CloseHandle( gRMxServerQuitDoneEvent );
280 check_translated_errno( ok, errno_compat(), kUnknownErr );
281 gRMxServerQuitDoneEvent = NULL;
282 }
283
284 RMxFinalize();
285 }
286
287 //===========================================================================================================================
288 // RMxServerRun
289 //===========================================================================================================================
290
291 OSStatus RMxServerRun( void )
292 {
293 OSStatus err;
294 DWORD waitCount;
295 HANDLE waitHandles[ 3 ];
296
297 // Initialize the server run loop and set up the list of objects to wait for.
298
299 err = RMxServerRunInitialize();
300 require_noerr( err, exit );
301
302 waitCount = 0;
303 waitHandles[ waitCount++ ] = gRMxServerSocketEvents[ 0 ];
304 waitHandles[ waitCount++ ] = gRMxServerSocketEvents[ 1 ];
305 waitHandles[ waitCount++ ] = gRMxStateChangeEvent;
306 check( waitCount == sizeof_array( waitHandles ) );
307
308 // Main event loop. Process connection requests and state changes (i.e. quit).
309
310 while( gRMxState == kRMxStateRun )
311 {
312 DWORD result;
313
314 result = WaitForMultipleObjects( waitCount, waitHandles, FALSE, INFINITE );
315 if( ( result == WAIT_OBJECT_0 ) ||
316 ( result == ( WAIT_OBJECT_0 + 1 ) ) ) // Socket Events
317 {
318 SocketRef sock;
319 struct sockaddr_storage addr;
320 socklen_t addrSize;
321 DWORD index;
322
323 index = result - WAIT_OBJECT_0;
324 check( ( index == 0 ) || IsValidSocket( gRMxServerSockets[ index ] ) );
325
326 // The socket event is only set up to notify on connection requests so try to accept the connection.
327 // Note: It is possible for accept to fail if the client aborts the connection after the network stack
328 // sees the connection request, but before accept is called. See UNPv1 section 15.6 for more information.
329
330 addrSize = sizeof( addr );
331 sock = accept( gRMxServerSockets[ index ], (struct sockaddr *) &addr, &addrSize );
332 if( IsValidSocket( sock ) )
333 {
334 if( ( gRMxServerFlags & kRMxServerFlagsAllowRemote ) || SOCKADDR_IS_IP_LOOPBACK( &addr ) )
335 {
336 dlog( kDebugLevelNotice, "\n" DEBUG_NAME "accepting connection from %##a\n", &addr );
337
338 err = RMxSessionOpen( NULL, kRMxSessionFlagsNone, sock, RMxServerMessageCallBack, NULL, NULL,
339 kRMxOpCodeInvalid, NULL );
340 check_noerr( err );
341 }
342 else
343 {
344 dlog( kDebugLevelNotice, DEBUG_NAME "remote connection attempt from %##a when local-only\n", &addr );
345
346 err = close_compat( sock );
347 check_translated_errno( err == 0, errno_compat(), kUnknownErr );
348 }
349 }
350 else
351 {
352 err = errno_compat();
353 dlog( kDebugLevelWarning, DEBUG_NAME "connection abort before accept (%d %m)\n", err, err );
354 }
355 }
356 else if( result == ( WAIT_OBJECT_0 + 2 ) ) // State Change Event
357 {
358 dlog( kDebugLevelNotice, DEBUG_NAME "state change (%d)\n", gRMxState );
359 break;
360 }
361 else
362 {
363 err = (OSStatus) GetLastError();
364 dlog( kDebugLevelAlert, DEBUG_NAME "wait error: 0x%08X, %d (%m)\n", result, err, err );
365 err = (OSStatus) result;
366 goto exit;
367 }
368 }
369 err = kNoErr;
370
371 exit:
372 RMxServerRunFinalize();
373 return( err );
374 }
375
376 //===========================================================================================================================
377 // RMxServerRunInitialize
378 //===========================================================================================================================
379
380 DEBUG_LOCAL OSStatus RMxServerRunInitialize( void )
381 {
382 OSStatus err;
383 struct addrinfo hints;
384 struct addrinfo * addrList;
385 struct addrinfo * addr;
386 int nAddrs;
387 BOOL ok;
388 int option;
389
390 addrList = NULL;
391
392 // Set up a socket for each address (only expected to be a single IPv4 and optionally a single IPv6 address).
393 // Windows does not support IPv4-mapped IPv6 addresses so we have to create a separate socket for each type.
394
395 memset( &hints, 0, sizeof( hints ) );
396 hints.ai_flags = AI_PASSIVE;
397 hints.ai_family = AF_UNSPEC;
398 hints.ai_socktype = SOCK_STREAM;
399 hints.ai_protocol = IPPROTO_TCP;
400
401 err = getaddrinfo( NULL, kRMxServerPortString, &hints, &addrList );
402 require_noerr( err, exit );
403
404 nAddrs = 0;
405 for( addr = addrList; addr; addr = addr->ai_next )
406 {
407 dlog( kDebugLevelTrace, DEBUG_NAME "setting up %s socket\n",
408 ( addr->ai_family == AF_INET ) ? "AF_INET" : ( addr->ai_family == AF_INET6 ) ? "AF_INET6" : "<unknown>" );
409 if( nAddrs > 1 )
410 {
411 dlog( kDebugLevelWarning, DEBUG_NAME "cannot handle more than 2 listening sockets (unexpected)\n" );
412 break;
413 }
414
415 gRMxServerSockets[ nAddrs ] = socket( addr->ai_family, addr->ai_socktype, addr->ai_protocol );
416 err = translate_errno( IsValidSocket( gRMxServerSockets[ nAddrs ] ), errno_compat(), kNoResourcesErr );
417 if( err != kNoErr )
418 {
419 dlog( kDebugLevelNotice, DEBUG_NAME "%s socket not supported (%d %m)\n",
420 ( addr->ai_family == AF_INET ) ? "AF_INET" : ( addr->ai_family == AF_INET6 ) ? "AF_INET6" : "<unknown>",
421 err, err );
422 continue;
423 }
424
425 // Enable the address-reuse option so the server can be stopped and re-started without the TIME_WAIT delay.
426
427 option = 1;
428 err = setsockopt( gRMxServerSockets[ nAddrs ], SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
429 err = translate_errno( err == 0, errno_compat(), kInUseErr );
430 require_noerr( err, exit );
431
432 // Set up to signal an event when a connection can be accepted so we can wait for it with WaitForMultipleObjects.
433 // Note: WSAEventSelect makes the socket non-blocking so it does not need to made non-blocking separately.
434
435 gRMxServerSocketEvents[ nAddrs ] = CreateEvent( NULL, FALSE, FALSE, NULL );
436 err = translate_errno( gRMxServerSocketEvents[ nAddrs ], errno_compat(), kNoResourcesErr );
437 require_noerr( err, exit );
438
439 err = WSAEventSelect( gRMxServerSockets[ nAddrs ], gRMxServerSocketEvents[ nAddrs ], FD_ACCEPT );
440 err = translate_errno( err == 0, errno_compat(), kInUseErr );
441 require_noerr( err, exit );
442
443 // Bind to the server port and enable listening for connections.
444
445 err = bind( gRMxServerSockets[ nAddrs ], addr->ai_addr, (int) addr->ai_addrlen );
446 err = translate_errno( err == 0, errno_compat(), kNoResourcesErr );
447 require_noerr( err, exit );
448
449 err = listen( gRMxServerSockets[ nAddrs ], SOMAXCONN );
450 err = translate_errno( err == 0, errno_compat(), kNoResourcesErr );
451 require_noerr( err, exit );
452
453 ++nAddrs;
454 }
455 require_action( nAddrs > 0, exit, err = kUnknownErr );
456
457 // Create a dummy event (which will never be signaled) to simplify WaitForMultipleObjects usage,
458
459 if( !gRMxServerSocketEvents[ 1 ] )
460 {
461 gRMxServerSocketEvents[ 1 ] = CreateEvent( NULL, FALSE, FALSE, NULL );
462 err = translate_errno( gRMxServerSocketEvents[ 1 ], errno_compat(), kNoResourcesErr );
463 require_noerr( err, exit );
464 }
465
466 // Reset the quit event to an unsignaled state so other code can wait for the run loop to quit.
467
468 gRMxState = kRMxStateRun;
469 ok = ResetEvent( gRMxServerQuitDoneEvent );
470 err = translate_errno( ok, errno_compat(), kUnknownErr );
471 require_noerr( err, exit );
472
473 exit:
474 if( addrList )
475 {
476 freeaddrinfo( addrList );
477 }
478 if( err != kNoErr )
479 {
480 RMxServerRunFinalize();
481 }
482 return( err );
483 }
484
485 //===========================================================================================================================
486 // RMxServerRunFinalize
487 //
488 // Note: This routine is safe to call multiple times (for easier cleanup).
489 //===========================================================================================================================
490
491 DEBUG_LOCAL void RMxServerRunFinalize( void )
492 {
493 OSStatus err;
494 BOOL ok;
495
496 // Release the socket events
497
498 if( gRMxServerSocketEvents[ 0 ] )
499 {
500 ok = CloseHandle( gRMxServerSocketEvents[ 0 ] );
501 check_translated_errno( ok, errno_compat(), kUnknownErr );
502 gRMxServerSocketEvents[ 0 ] = NULL;
503 }
504 if( gRMxServerSocketEvents[ 1 ] )
505 {
506 ok = CloseHandle( gRMxServerSocketEvents[ 1 ] );
507 check_translated_errno( ok, errno_compat(), kUnknownErr );
508 gRMxServerSocketEvents[ 1 ] = NULL;
509 }
510
511 // Close the sockets.
512
513 if( IsValidSocket( gRMxServerSockets[ 0 ] ) )
514 {
515 err = close_compat( gRMxServerSockets[ 0 ] );
516 check_translated_errno( err == 0, errno_compat(), kUnknownErr );
517 gRMxServerSockets[ 0 ] = kInvalidSocketRef;
518 }
519 if( IsValidSocket( gRMxServerSockets[ 1 ] ) )
520 {
521 err = close_compat( gRMxServerSockets[ 1 ] );
522 check_translated_errno( err == 0, errno_compat(), kUnknownErr );
523 gRMxServerSockets[ 1 ] = kInvalidSocketRef;
524 }
525
526 // Signal the quit event to indicate the run loop has quit.
527
528 ok = SetEvent( gRMxServerQuitDoneEvent );
529 check_translated_errno( ok, errno_compat(), kUnknownErr );
530 }
531
532 //===========================================================================================================================
533 // RMxServerStop
534 //===========================================================================================================================
535
536 OSStatus RMxServerStop( RMxServerStopFlags inFlags )
537 {
538 BOOL ok;
539 DWORD result;
540
541 // Signal a state changed event to trigger everything to stop. Note: This is a manual-reset event so it will
542 // remain signaled to allow all running threads to wake up and exit cleanly.
543
544 gRMxState = kRMxStateStop;
545 if( gRMxStateChangeEvent )
546 {
547 ok = SetEvent( gRMxStateChangeEvent );
548 check_translated_errno( ok, errno_compat(), kUnknownErr );
549 }
550
551 // Wait for the quit event indicating the run loop has quit. Give up after 10 seconds to handle a hung thread.
552
553 if( !( inFlags & kRMxServerStopFlagsNoWait ) )
554 {
555 if( gRMxServerQuitDoneEvent )
556 {
557 result = WaitForSingleObject( gRMxServerQuitDoneEvent, 10 * 1000 );
558 check_translated_errno( result == WAIT_OBJECT_0, errno_compat(), result );
559 }
560 }
561
562 return( kNoErr );
563 }
564
565 //===========================================================================================================================
566 // RMxServerMessageCallBack
567 //===========================================================================================================================
568
569 DEBUG_LOCAL void RMxServerMessageCallBack( RMxMessage *inMessage )
570 {
571 DNSServiceRef obj;
572 OSStatus err;
573
574 check( inMessage );
575 check( inMessage->session );
576
577 switch( inMessage->opcode )
578 {
579 // General
580
581 case kRMxOpCodeInvalid:
582
583 // The session is closing so delete the object (if still valid). Invalidate the session because the session
584 // is already in the process of closing so we don't want the deallocate code closing it again.
585
586 obj = (DNSServiceRef) inMessage->context;
587 if( obj )
588 {
589 obj->sessionClosing = true;
590 DNSServiceRefDeallocate_server( obj );
591 }
592 break;
593
594 case kRMxOpCodeCheckVersion:
595 DNSServiceCheckVersion_server( inMessage );
596 break;
597
598 // Properties
599
600 case kRMxOpCodeCopyProperty:
601 DNSServiceCopyProperty_server( inMessage );
602 break;
603
604 // Domain Enumeration
605
606 case kRMxOpCodeEnumerateDomains:
607 DNSServiceEnumerateDomains_server( inMessage );
608 break;
609
610 // Service Registration
611
612 case kRMxOpCodeRegister:
613 DNSServiceRegister_server( inMessage );
614 break;
615
616 case kRMxOpCodeAddRecord:
617 DNSServiceAddRecord_server( inMessage );
618 break;
619
620 case kRMxOpCodeUpdateRecord:
621 DNSServiceUpdateRecord_server( inMessage );
622 break;
623
624 case kRMxOpCodeRemoveRecord:
625 DNSServiceRemoveRecord_server( inMessage );
626 break;
627
628 // Service Discovery
629
630 case kRMxOpCodeBrowse:
631 DNSServiceBrowse_server( inMessage );
632 break;
633
634 case kRMxOpCodeResolve:
635 DNSServiceResolve_server( inMessage );
636 break;
637
638 // Special Purpose
639
640 case kRMxOpCodeCreateConnection:
641 DNSServiceCreateConnection_server( inMessage );
642 break;
643
644 case kRMxOpCodeRegisterRecord:
645 DNSServiceRegisterRecord_server( inMessage );
646 break;
647
648 case kRMxOpCodeQueryRecord:
649 DNSServiceQueryRecord_server( inMessage );
650 break;
651
652 case kRMxOpCodeReconfirmRecord:
653 DNSServiceReconfirmRecord_server( inMessage );
654 break;
655
656 default:
657 dlog( kDebugLevelWarning, DEBUG_NAME "message with unknown opcode received (%d)\n", inMessage->opcode );
658 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, kUnsupportedErr, "" );
659 check_noerr( err );
660 break;
661 }
662 }
663
664 #if 0
665 #pragma mark -
666 #pragma mark == DNS-SD General ==
667 #endif
668
669 //===========================================================================================================================
670 // DNSServiceRefDeallocate_server
671 //===========================================================================================================================
672
673 DEBUG_LOCAL void DNSServiceRefDeallocate_server( DNSServiceRef inRef )
674 {
675 OSStatus err;
676
677 check( inRef );
678
679 dlog( kDebugLevelTrace, DEBUG_NAME "%s: ref=%#p\n", __ROUTINE__, inRef );
680
681 // Release the direct object if active.
682
683 if( inRef->directObj )
684 {
685 DNSServiceRefDeallocate_direct( inRef->directObj );
686 }
687
688 // Close the session.
689
690 if( inRef->session && !inRef->sessionClosing )
691 {
692 inRef->session->callback = NULL;
693 inRef->session->message.context = NULL;
694
695 err = RMxSessionClose( inRef->session, kEndingErr );
696 check_noerr( err );
697 }
698
699 // Release any extra records.
700
701 while( inRef->records )
702 {
703 DNSRecordRef record;
704
705 record = inRef->records;
706 inRef->records = record->next;
707
708 free( record );
709 }
710
711 // Release the object.
712
713 free( inRef );
714 }
715
716 //===========================================================================================================================
717 // DNSServiceCheckVersion_server
718 //===========================================================================================================================
719
720 DEBUG_LOCAL void DNSServiceCheckVersion_server( RMxMessage *inMessage )
721 {
722 OSStatus err;
723 uint32_t clientCurrentVersion;
724 uint32_t clientOldestClientVersion;
725 uint32_t clientOldestServerVersion;
726
727 check( inMessage );
728 check( inMessage->session );
729
730 // Extract parameters from the message.
731
732 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "www",
733 &clientCurrentVersion, &clientOldestClientVersion, &clientOldestServerVersion );
734 require_noerr( err, exit );
735
736 dlog( kDebugLevelTrace, DEBUG_NAME "%s: clientCurrent=%v, clientOldestClient=%v, clientOldestServer=%v\n",
737 __ROUTINE__, clientCurrentVersion, clientOldestClientVersion, clientOldestServerVersion );
738
739 err = RMxCheckVersion( clientCurrentVersion, clientOldestClientVersion, clientOldestServerVersion,
740 kRMxCurrentVersion, kRMxOldestClientVersion, kRMxOldestServerVersion );
741
742 // Send the response and our version information. Cause the session to quit since this is a one-shot session.
743
744 exit:
745 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, kNoErr, "wwww",
746 err, kRMxCurrentVersion, kRMxOldestClientVersion, kRMxOldestServerVersion );
747 check_noerr( err );
748
749 inMessage->session->quit = true;
750 }
751
752 #if 0
753 #pragma mark -
754 #pragma mark == DNS-SD Properties ==
755 #endif
756
757 //===========================================================================================================================
758 // DNSServiceCopyProperty_server
759 //===========================================================================================================================
760
761 DEBUG_LOCAL void DNSServiceCopyProperty_server( RMxMessage *inMessage )
762 {
763 OSStatus err;
764 DNSPropertyCode code;
765
766 check( inMessage );
767 check( inMessage->session );
768
769 // Extract parameters from the message.
770
771 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "w", &code );
772 require_noerr( err, exit );
773
774 dlog( kDebugLevelTrace, DEBUG_NAME "%s: code='%C'\n", __ROUTINE__, code );
775
776
777 // Send the response and our version information. Cause the session to quit since this is a one-shot session.
778
779 exit:
780 err = DNSServiceCopyPropertySendData_server( code, inMessage );
781 check_noerr( err );
782
783 inMessage->session->quit = true;
784 }
785
786 //===========================================================================================================================
787 // DNSServiceCopyPropertySendData_server
788 //===========================================================================================================================
789
790 DEBUG_LOCAL OSStatus DNSServiceCopyPropertySendData_server( DNSPropertyCode inCode, RMxMessage *inMessage )
791 {
792 OSStatus err;
793
794 switch( inCode )
795 {
796 case kDNSPropertyCodeVersion:
797
798 // Note: This manually builds the "n" data type using a "w" size followed by the data to avoid a temporary buffer.
799
800 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, kNoErr, "ww wwww", kNoErr, inCode,
801 4 + 4 + 4, kRMxCurrentVersion, kRMxOldestClientVersion, kRMxOldestServerVersion );
802 require_noerr( err, exit );
803 break;
804
805 default:
806 dlog( kDebugLevelWarning, DEBUG_NAME "%s: unknown property code (%C)\n", __ROUTINE__, inCode );
807 err = kDNSServiceErr_Unsupported;
808 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, kNoErr, "wn", err, 0, NULL );
809 require_noerr( err, exit );
810 break;
811 }
812 err = kNoErr;
813
814 exit:
815 return( err );
816 }
817
818 #if 0
819 #pragma mark DNSServiceReleaseProperty_server
820 #endif
821
822 // Note: DNSServiceReleaseProperty_server is not needed on the server side because memory is released immediately after sending.
823
824 #if 0
825 #pragma mark -
826 #pragma mark == DNS-SD Domain Enumeration ==
827 #endif
828
829 //===========================================================================================================================
830 // DNSServiceEnumerateDomains_server
831 //===========================================================================================================================
832
833 DEBUG_LOCAL void DNSServiceEnumerateDomains_server( RMxMessage *inMessage )
834 {
835 OSStatus err;
836 DNSServiceRef obj;
837 DNSServiceFlags flags;
838 uint32_t interfaceIndex;
839
840 obj = NULL;
841 check( inMessage );
842 check( inMessage->session );
843 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
844
845 // Extract parameters from the message.
846
847 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "ww", &flags, &interfaceIndex );
848 require_noerr( err, exit );
849
850 dlog( kDebugLevelTrace, DEBUG_NAME "%s: flags=0x%08X, ifi=%d\n", __ROUTINE__, flags, interfaceIndex );
851
852 // Allocate and initialize the object.
853
854 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
855 require_action( obj, exit, err = kNoMemoryErr );
856
857 obj->opcode = inMessage->opcode;
858 obj->session = inMessage->session;
859
860 err = DNSServiceEnumerateDomains_direct( &obj->directObj, flags, interfaceIndex,
861 DNSServiceEnumerateDomainsCallBack_server, obj );
862 require_noerr( err, exit );
863
864 // Success!
865
866 inMessage->session->message.context = obj;
867 obj = NULL;
868
869 exit:
870 if( err != kNoErr )
871 {
872 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
873 check_noerr( err );
874 }
875 if( obj )
876 {
877 DNSServiceRefDeallocate_server( obj );
878 }
879 }
880
881 //===========================================================================================================================
882 // DNSServiceEnumerateDomainsCallBack_server
883 //===========================================================================================================================
884
885 DEBUG_LOCAL void CALLBACK_COMPAT
886 DNSServiceEnumerateDomainsCallBack_server(
887 DNSServiceRef inRef,
888 DNSServiceFlags inFlags,
889 uint32_t inInterfaceIndex,
890 DNSServiceErrorType inErrorCode,
891 const char * inDomain,
892 void * inContext )
893 {
894 DNSServiceRef obj;
895 OSStatus err;
896
897 DEBUG_UNUSED( inRef );
898
899 check( inDomain );
900 obj = (DNSServiceRef) inContext;
901 check( obj );
902 check( obj->session );
903
904 err = RMxSessionSendMessage( obj->session, kRMxOpCodeEnumerateDomains, kNoErr, "wwws",
905 inFlags, inInterfaceIndex, inErrorCode, inDomain );
906 check_noerr( err );
907 }
908
909 #if 0
910 #pragma mark -
911 #pragma mark == DNS-SD Service Registration ==
912 #endif
913
914 //===========================================================================================================================
915 // DNSServiceRegister_server
916 //===========================================================================================================================
917
918 DEBUG_LOCAL void DNSServiceRegister_server( RMxMessage *inMessage )
919 {
920 OSStatus err;
921 DNSServiceRef obj;
922 DNSServiceFlags flags;
923 uint32_t interfaceIndex;
924 const char * name;
925 const char * type;
926 const char * domain;
927 const char * host;
928 uint16_t port;
929 const void * txt;
930 size_t txtSize;
931
932 obj = NULL;
933 check( inMessage );
934 check( inMessage->session );
935 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
936
937 // Extract parameters from the message.
938
939 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwsssshn",
940 &flags, &interfaceIndex, &name, NULL, &type, NULL, &domain, NULL, &host, NULL, &port, &txt, &txtSize );
941 require_noerr( err, exit );
942
943 dlog( kDebugLevelTrace, DEBUG_NAME
944 "%s: flags=0x%08X, ifi=%ld, name=\"%s\", type=\"%s\", domain=\"%s\", host=\"%s\", port=%d, txtSize=%d\n",
945 __ROUTINE__, flags, interfaceIndex, name, type, domain, host, ntohs( port ), txtSize );
946
947 // Allocate and initialize the object.
948
949 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
950 require_action( obj, exit, err = kNoMemoryErr );
951
952 obj->opcode = inMessage->opcode;
953 obj->session = inMessage->session;
954
955 err = DNSServiceRegister_direct( &obj->directObj, flags, interfaceIndex, name, type, domain, host, port,
956 (uint16_t) txtSize, txt, DNSServiceRegisterCallBack_server, obj );
957 require_noerr( err, exit );
958
959 // Success!
960
961 inMessage->session->message.context = obj;
962 obj = NULL;
963
964 exit:
965 if( err != kNoErr )
966 {
967 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
968 check_noerr( err );
969 }
970 if( obj )
971 {
972 DNSServiceRefDeallocate_server( obj );
973 }
974 }
975
976 //===========================================================================================================================
977 // DNSServiceRegisterCallBack_server
978 //===========================================================================================================================
979
980 DEBUG_LOCAL void CALLBACK_COMPAT
981 DNSServiceRegisterCallBack_server(
982 DNSServiceRef inRef,
983 DNSServiceFlags inFlags,
984 DNSServiceErrorType inErrorCode,
985 const char * inName,
986 const char * inType,
987 const char * inDomain,
988 void * inContext )
989 {
990 DNSServiceRef obj;
991 OSStatus err;
992
993 DEBUG_UNUSED( inRef );
994
995 check( inDomain );
996 obj = (DNSServiceRef) inContext;
997 check( obj );
998 check( obj->session );
999
1000 err = RMxSessionSendMessage( obj->session, kRMxOpCodeRegister, kNoErr, "wwsss",
1001 inFlags, inErrorCode, inName, inType, inDomain );
1002 check_noerr( err );
1003 }
1004
1005 //===========================================================================================================================
1006 // DNSServiceAddRecord_server
1007 //===========================================================================================================================
1008
1009 DEBUG_LOCAL void DNSServiceAddRecord_server( RMxMessage *inMessage )
1010 {
1011 OSStatus err;
1012 DNSRecordRef obj;
1013 DNSServiceRef ref;
1014 uint32_t id;
1015 DNSServiceFlags flags;
1016 uint16_t rrType;
1017 uint8_t * rData;
1018 size_t rDataSize;
1019 uint32_t ttl;
1020 DNSRecordRef * p;
1021
1022 obj = NULL;
1023 check( inMessage );
1024 check( inMessage->session );
1025 ref = (DNSServiceRef) inMessage->context;
1026 require_action( ref, exit, err = kNotInitializedErr );
1027 require_action( ref->opcode == kRMxOpCodeRegister, exit, err = kTypeErr );
1028 check( ref->directObj );
1029
1030 // Extract parameters from the message.
1031
1032 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwhnw", &id, &flags, &rrType, &rData, &rDataSize, &ttl );
1033 require_noerr( err, exit );
1034
1035 dlog( kDebugLevelTrace, DEBUG_NAME "%s: id=%d, flags=0x%08X, rrType=%d, rDataSize=%d, ttl=%d\n",
1036 __ROUTINE__, id, flags, rrType, rDataSize, ttl );
1037
1038 // Allocate and initialize the object and add it to the list of records.
1039
1040 obj = (DNSRecordRef) calloc( 1, sizeof( *obj ) );
1041 require_action( obj, exit, err = kNoMemoryErr );
1042
1043 obj->id = id;
1044
1045 obj->next = ref->records;
1046 ref->records = obj;
1047
1048 err = DNSServiceAddRecord_direct( ref->directObj, &obj->directObj, flags, rrType, (uint16_t) rDataSize, rData, ttl );
1049 require_noerr( err, exit );
1050
1051 obj = NULL;
1052
1053 exit:
1054 if( err != kNoErr )
1055 {
1056 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1057 check_noerr( err );
1058 }
1059 if( obj )
1060 {
1061 for( p = &ref->records; *p; p = &( *p )->next )
1062 {
1063 if( *p == obj )
1064 {
1065 *p = obj->next;
1066 free( obj );
1067 break;
1068 }
1069 }
1070 }
1071 }
1072
1073 //===========================================================================================================================
1074 // DNSServiceUpdateRecord_server
1075 //===========================================================================================================================
1076
1077 DEBUG_LOCAL void DNSServiceUpdateRecord_server( RMxMessage *inMessage )
1078 {
1079 OSStatus err;
1080 DNSServiceRef ref;
1081 uint32_t id;
1082 DNSServiceFlags flags;
1083 uint8_t * rData;
1084 size_t rDataSize;
1085 uint32_t ttl;
1086 DNSRecordRef obj;
1087
1088 check( inMessage );
1089 check( inMessage->session );
1090 ref = (DNSServiceRef) inMessage->context;
1091 require_action( ref, exit, err = kNotInitializedErr );
1092 require_action( ( ref->opcode == kRMxOpCodeRegister ) || ( ref->opcode == kRMxOpCodeCreateConnection ), exit, err = kTypeErr );
1093 check( ref->directObj );
1094
1095 // Extract parameters from the message.
1096
1097 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwnw", &id, &flags, &rData, &rDataSize, &ttl );
1098 require_noerr( err, exit );
1099
1100 dlog( kDebugLevelTrace, DEBUG_NAME "%s: id=%d, flags=0x%08X, rDataSize=%d, ttl=%d\n", __ROUTINE__, id, flags, rDataSize, ttl );
1101
1102 // Find the record with the specified ID and update it.
1103
1104 if( id == kDNSRecordIndexDefaultTXT )
1105 {
1106 obj = NULL;
1107 }
1108 else
1109 {
1110 for( obj = ref->records; obj; obj = obj->next )
1111 {
1112 if( obj->id == id )
1113 {
1114 break;
1115 }
1116 }
1117 require_action( obj, exit, err = kNotFoundErr );
1118 check( obj->directObj );
1119 }
1120
1121 err = DNSServiceUpdateRecord_direct( ref->directObj, obj->directObj, flags, (uint16_t) rDataSize, rData, ttl );
1122 require_noerr( err, exit );
1123
1124 exit:
1125 if( err != kNoErr )
1126 {
1127 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1128 check_noerr( err );
1129 }
1130 }
1131
1132 //===========================================================================================================================
1133 // DNSServiceRemoveRecord_server
1134 //===========================================================================================================================
1135
1136 DEBUG_LOCAL void DNSServiceRemoveRecord_server( RMxMessage *inMessage )
1137 {
1138 OSStatus err;
1139 DNSServiceRef ref;
1140 uint32_t id;
1141 DNSServiceFlags flags;
1142 DNSRecordRef * p;
1143 DNSRecordRef obj;
1144 DNSRecordRef directObj;
1145
1146 check( inMessage );
1147 check( inMessage->session );
1148 ref = (DNSServiceRef) inMessage->context;
1149 require_action( ref, exit, err = kNotInitializedErr );
1150 require_action( ( ref->opcode == kRMxOpCodeRegister ) || ( ref->opcode == kRMxOpCodeCreateConnection ), exit, err = kTypeErr );
1151 check( ref->directObj );
1152
1153 // Extract parameters from the message.
1154
1155 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "ww", &id, &flags );
1156 require_noerr( err, exit );
1157
1158 dlog( kDebugLevelTrace, DEBUG_NAME "%s: id=%d, flags=0x%08X\n", __ROUTINE__, id, flags );
1159
1160 // Find the record with the specified ID, remove it from the list, and free it.
1161
1162 for( p = &ref->records; *p; p = &( *p )->next )
1163 {
1164 if( ( *p )->id == id )
1165 {
1166 break;
1167 }
1168 }
1169 obj = *p;
1170 require_action( obj, exit, err = kNotFoundErr );
1171 *p = obj->next;
1172
1173 directObj = obj->directObj;
1174 check( directObj );
1175 free( obj );
1176
1177 err = DNSServiceRemoveRecord_direct( ref->directObj, directObj, flags );
1178 require_noerr( err, exit );
1179
1180 exit:
1181 if( err != kNoErr )
1182 {
1183 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1184 check_noerr( err );
1185 }
1186 }
1187
1188 #if 0
1189 #pragma mark -
1190 #pragma mark == DNS-SD Service Discovery ==
1191 #endif
1192
1193 //===========================================================================================================================
1194 // DNSServiceBrowse_server
1195 //===========================================================================================================================
1196
1197 DEBUG_LOCAL void DNSServiceBrowse_server( RMxMessage *inMessage )
1198 {
1199 OSStatus err;
1200 DNSServiceRef obj;
1201 DNSServiceFlags flags;
1202 uint32_t interfaceIndex;
1203 const char * type;
1204 const char * domain;
1205
1206 obj = NULL;
1207 check( inMessage );
1208 check( inMessage->session );
1209 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
1210
1211 // Extract parameters from the message.
1212
1213 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwss", &flags, &interfaceIndex, &type, NULL, &domain, NULL );
1214 require_noerr( err, exit );
1215
1216 dlog( kDebugLevelTrace, DEBUG_NAME "%s: flags=0x%08X, ifi=%d, type=\"%s\", domain=\"%s\"\n",
1217 __ROUTINE__, flags, interfaceIndex, type, domain );
1218
1219 // Allocate and initialize the object.
1220
1221 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
1222 require_action( obj, exit, err = kNoMemoryErr );
1223
1224 obj->opcode = inMessage->opcode;
1225 obj->session = inMessage->session;
1226
1227 err = DNSServiceBrowse_direct( &obj->directObj, flags, interfaceIndex, type, domain, DNSServiceBrowseCallBack_server, obj );
1228 require_noerr( err, exit );
1229
1230 // Success!
1231
1232 inMessage->session->message.context = obj;
1233 obj = NULL;
1234
1235 exit:
1236 if( err != kNoErr )
1237 {
1238 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1239 check_noerr( err );
1240 }
1241 if( obj )
1242 {
1243 DNSServiceRefDeallocate_server( obj );
1244 }
1245 }
1246
1247 //===========================================================================================================================
1248 // DNSServiceBrowseCallBack_server
1249 //===========================================================================================================================
1250
1251 DEBUG_LOCAL void CALLBACK_COMPAT
1252 DNSServiceBrowseCallBack_server(
1253 DNSServiceRef inRef,
1254 DNSServiceFlags inFlags,
1255 uint32_t inInterfaceIndex,
1256 DNSServiceErrorType inErrorCode,
1257 const char * inName,
1258 const char * inType,
1259 const char * inDomain,
1260 void * inContext )
1261 {
1262 DNSServiceRef obj;
1263 OSStatus err;
1264
1265 DEBUG_UNUSED( inRef );
1266
1267 check( inName );
1268 check( inType );
1269 check( inDomain );
1270 obj = (DNSServiceRef) inContext;
1271 check( obj );
1272 check( obj->session );
1273
1274 err = RMxSessionSendMessage( obj->session, kRMxOpCodeBrowse, kNoErr, "wwwsss",
1275 inFlags, inInterfaceIndex, inErrorCode, inName, inType, inDomain );
1276 check_noerr( err );
1277 }
1278
1279 #if 0
1280 #pragma mark -
1281 #endif
1282
1283 //===========================================================================================================================
1284 // DNSServiceResolve_server
1285 //===========================================================================================================================
1286
1287 DEBUG_LOCAL void DNSServiceResolve_server( RMxMessage *inMessage )
1288 {
1289 OSStatus err;
1290 DNSServiceRef obj;
1291 DNSServiceFlags flags;
1292 uint32_t interfaceIndex;
1293 const char * name;
1294 const char * type;
1295 const char * domain;
1296
1297 obj = NULL;
1298 check( inMessage );
1299 check( inMessage->session );
1300 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
1301
1302 // Extract parameters from the message.
1303
1304 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwsss",
1305 &flags, &interfaceIndex, &name, NULL, &type, NULL, &domain, NULL );
1306 require_noerr( err, exit );
1307
1308 dlog( kDebugLevelTrace, DEBUG_NAME "%s: flags=0x%08X, ifi=%d, name=\"%s\", type=\"%s\", domain=\"%s\"\n",
1309 __ROUTINE__, flags, interfaceIndex, name, type, domain );
1310
1311 // Allocate and initialize the object.
1312
1313 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
1314 require_action( obj, exit, err = kNoMemoryErr );
1315
1316 obj->opcode = inMessage->opcode;
1317 obj->session = inMessage->session;
1318
1319 err = DNSServiceResolve_direct( &obj->directObj, flags, interfaceIndex, name, type, domain,
1320 DNSServiceResolveCallBack_server, obj );
1321 require_noerr( err, exit );
1322
1323 // Success!
1324
1325 inMessage->session->message.context = obj;
1326 obj = NULL;
1327
1328 exit:
1329 if( err != kNoErr )
1330 {
1331 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1332 check_noerr( err );
1333 }
1334 if( obj )
1335 {
1336 DNSServiceRefDeallocate_server( obj );
1337 }
1338 }
1339
1340 //===========================================================================================================================
1341 // DNSServiceResolveCallBack_server
1342 //===========================================================================================================================
1343
1344 DEBUG_LOCAL void CALLBACK_COMPAT
1345 DNSServiceResolveCallBack_server(
1346 DNSServiceRef inRef,
1347 DNSServiceFlags inFlags,
1348 uint32_t inInterfaceIndex,
1349 DNSServiceErrorType inErrorCode,
1350 const char * inFullName,
1351 const char * inHostName,
1352 uint16_t inPort,
1353 uint16_t inTXTSize,
1354 const char * inTXT,
1355 void * inContext )
1356 {
1357 DNSServiceRef obj;
1358 OSStatus err;
1359
1360 DEBUG_UNUSED( inRef );
1361
1362 check( inFullName );
1363 check( inHostName );
1364 obj = (DNSServiceRef) inContext;
1365 dlog( kDebugLevelTrace, DEBUG_NAME "%s: ref=%#p, directRef=%#p\n", __ROUTINE__, obj, inRef );
1366 check( obj );
1367 check( obj->session );
1368
1369 err = RMxSessionSendMessage( obj->session, kRMxOpCodeResolve, kNoErr, "wwwsshn",
1370 inFlags, inInterfaceIndex, inErrorCode, inFullName, inHostName, inPort, inTXTSize, inTXT );
1371 check_noerr( err );
1372 }
1373
1374 #if 0
1375 #pragma mark -
1376 #pragma mark == DNS-SD Special Purpose ==
1377 #endif
1378
1379 //===========================================================================================================================
1380 // DNSServiceCreateConnection_server
1381 //===========================================================================================================================
1382
1383 DEBUG_LOCAL void DNSServiceCreateConnection_server( RMxMessage *inMessage )
1384 {
1385 OSStatus err;
1386 DNSServiceRef obj;
1387
1388 obj = NULL;
1389 check( inMessage );
1390 check( inMessage->session );
1391 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
1392
1393 dlog( kDebugLevelTrace, DEBUG_NAME "%s\n", __ROUTINE__ );
1394
1395 // Allocate and initialize the object.
1396
1397 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
1398 require_action( obj, exit, err = kNoMemoryErr );
1399
1400 obj->opcode = inMessage->opcode;
1401 obj->session = inMessage->session;
1402
1403 err = DNSServiceCreateConnection_direct( &obj->directObj );
1404 require_noerr( err, exit );
1405
1406 // Success!
1407
1408 inMessage->session->message.context = obj;
1409 obj = NULL;
1410
1411 exit:
1412 if( err != kNoErr )
1413 {
1414 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1415 check_noerr( err );
1416 }
1417 if( obj )
1418 {
1419 DNSServiceRefDeallocate_server( obj );
1420 }
1421 }
1422
1423 //===========================================================================================================================
1424 // DNSServiceRegisterRecord_server
1425 //===========================================================================================================================
1426
1427 DEBUG_LOCAL void DNSServiceRegisterRecord_server( RMxMessage *inMessage )
1428 {
1429 OSStatus err;
1430 DNSRecordRef obj;
1431 DNSServiceRef ref;
1432 uint32_t id;
1433 DNSServiceFlags flags;
1434 uint32_t interfaceIndex;
1435 const char * name;
1436 uint16_t rrType;
1437 uint16_t rrClass;
1438 uint8_t * rData;
1439 size_t rDataSize;
1440 uint32_t ttl;
1441 DNSRecordRef * p;
1442
1443 obj = NULL;
1444 check( inMessage );
1445 check( inMessage->session );
1446 ref = (DNSServiceRef) inMessage->context;
1447 require_action( ref, exit, err = kNotInitializedErr );
1448 require_action( ref->opcode == kRMxOpCodeCreateConnection, exit, err = kTypeErr );
1449 check( ref->directObj );
1450
1451 // Extract parameters from the message.
1452
1453 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwwshhnw",
1454 &id, &flags, &interfaceIndex, &name, NULL, &rrType, &rrClass, &rData, &rDataSize, &ttl );
1455 require_noerr( err, exit );
1456
1457 dlog( kDebugLevelTrace, DEBUG_NAME
1458 "%s: id=%d, flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d, rDataSize=%d, ttl=%d\n",
1459 __ROUTINE__, id, flags, interfaceIndex, name, rrType, rrClass, rDataSize, ttl );
1460
1461 // Allocate and initialize the object and add it to the list of records.
1462
1463 obj = (DNSRecordRef) calloc( 1, sizeof( *obj ) );
1464 require_action( obj, exit, err = kNoMemoryErr );
1465
1466 obj->id = id;
1467 obj->owner = ref;
1468
1469 obj->next = ref->records;
1470 ref->records = obj;
1471
1472 err = DNSServiceRegisterRecord_direct( ref->directObj, &obj->directObj, flags, interfaceIndex, name, rrType, rrClass,
1473 (uint16_t) rDataSize, rData, ttl, DNSServiceRegisterRecordCallBack_server, obj );
1474 require_noerr( err, exit );
1475
1476 obj = NULL;
1477
1478 exit:
1479 if( err != kNoErr )
1480 {
1481 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1482 check_noerr( err );
1483 }
1484 if( obj )
1485 {
1486 for( p = &ref->records; *p; p = &( *p )->next )
1487 {
1488 if( *p == obj )
1489 {
1490 *p = obj->next;
1491 free( obj );
1492 break;
1493 }
1494 }
1495 }
1496 }
1497
1498 //===========================================================================================================================
1499 // DNSServiceRegisterRecordCallBack_server
1500 //===========================================================================================================================
1501
1502 DEBUG_LOCAL void CALLBACK_COMPAT
1503 DNSServiceRegisterRecordCallBack_server(
1504 DNSServiceRef inRef,
1505 DNSRecordRef inRecordRef,
1506 DNSServiceFlags inFlags,
1507 DNSServiceErrorType inErrorCode,
1508 void * inContext )
1509 {
1510 DNSRecordRef record;
1511 DNSServiceRef obj;
1512 OSStatus err;
1513
1514 DEBUG_UNUSED( inRef );
1515 DEBUG_UNUSED( inRecordRef );
1516
1517 record = (DNSRecordRef) inContext;
1518 check( record );
1519 obj = record->owner;
1520 check( obj );
1521 check( obj->session );
1522
1523 err = RMxSessionSendMessage( obj->session, kRMxOpCodeRegisterRecord, kNoErr, "www", inFlags, inErrorCode, record->id );
1524 check_noerr( err );
1525 }
1526
1527 //===========================================================================================================================
1528 // DNSServiceQueryRecord_server
1529 //===========================================================================================================================
1530
1531 DEBUG_LOCAL void DNSServiceQueryRecord_server( RMxMessage *inMessage )
1532 {
1533 OSStatus err;
1534 DNSServiceRef obj;
1535 DNSServiceFlags flags;
1536 uint32_t interfaceIndex;
1537 const char * name;
1538 uint16_t rrType;
1539 uint16_t rrClass;
1540
1541 obj = NULL;
1542 check( inMessage );
1543 check( inMessage->session );
1544 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
1545
1546 // Extract parameters from the message.
1547
1548 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwshh",
1549 &flags, &interfaceIndex, &name, NULL, &rrType, &rrClass );
1550 require_noerr( err, exit );
1551
1552 dlog( kDebugLevelTrace, DEBUG_NAME "%s: flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d\n",
1553 __ROUTINE__, flags, interfaceIndex, name, rrType, rrClass );
1554
1555 // Allocate and initialize the object.
1556
1557 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
1558 require_action( obj, exit, err = kNoMemoryErr );
1559
1560 obj->opcode = inMessage->opcode;
1561 obj->session = inMessage->session;
1562
1563 err = DNSServiceQueryRecord_direct( &obj->directObj, flags, interfaceIndex, name, rrType, rrClass,
1564 DNSServiceQueryRecordCallBack_server, obj );
1565 require_noerr( err, exit );
1566
1567 // Success!
1568
1569 inMessage->session->message.context = obj;
1570 obj = NULL;
1571
1572 exit:
1573 if( err != kNoErr )
1574 {
1575 err = RMxSessionSendMessage( inMessage->session, inMessage->opcode, err, "" );
1576 check_noerr( err );
1577 }
1578 if( obj )
1579 {
1580 DNSServiceRefDeallocate_server( obj );
1581 }
1582 }
1583
1584 //===========================================================================================================================
1585 // DNSServiceQueryRecordCallBack_server
1586 //===========================================================================================================================
1587
1588 DEBUG_LOCAL void CALLBACK_COMPAT
1589 DNSServiceQueryRecordCallBack_server(
1590 DNSServiceRef inRef,
1591 DNSServiceFlags inFlags,
1592 uint32_t inInterfaceIndex,
1593 DNSServiceErrorType inErrorCode,
1594 const char * inName,
1595 uint16_t inRRType,
1596 uint16_t inRRClass,
1597 uint16_t inRDataSize,
1598 const void * inRData,
1599 uint32_t inTTL,
1600 void * inContext )
1601 {
1602 DNSServiceRef obj;
1603 OSStatus err;
1604
1605 DEBUG_UNUSED( inRef );
1606
1607 obj = (DNSServiceRef) inContext;
1608 check( obj );
1609 check( obj->session );
1610
1611 err = RMxSessionSendMessage( obj->session, kRMxOpCodeQueryRecord, kNoErr, "wwwshhnw",
1612 inFlags, inInterfaceIndex, inErrorCode, inName, inRRType, inRRClass, inRDataSize, inRData, inTTL );
1613 check_noerr( err );
1614 }
1615
1616 //===========================================================================================================================
1617 // DNSServiceReconfirmRecord_server
1618 //===========================================================================================================================
1619
1620 DEBUG_LOCAL void DNSServiceReconfirmRecord_server( RMxMessage *inMessage )
1621 {
1622 OSStatus err;
1623 DNSServiceFlags flags;
1624 uint32_t interfaceIndex;
1625 const char * name;
1626 uint16_t rrType;
1627 uint16_t rrClass;
1628 uint8_t * rData;
1629 size_t rDataSize;
1630
1631 check( inMessage );
1632 check( inMessage->session );
1633 require_action( !inMessage->session->message.context, exit, err = kTypeErr );
1634
1635 // Extract parameters from the message.
1636
1637 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwshhn",
1638 &flags, &interfaceIndex, &name, NULL, &rrType, &rrClass, &rData, &rDataSize );
1639 require_noerr( err, exit );
1640
1641 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "%s: flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d, rDataSize=%d\n",
1642 __ROUTINE__, flags, interfaceIndex, name, rrType, rrClass, rDataSize );
1643
1644 // Trigger the reconfirm then cause the session to quit.
1645
1646 DNSServiceReconfirmRecord_direct( flags, interfaceIndex, name, rrType, rrClass, (uint16_t) rDataSize, rData );
1647 require_noerr( err, exit );
1648
1649 exit:
1650 inMessage->session->quit = true;
1651 return;
1652 }
1653
1654 #ifdef __cplusplus
1655 }
1656 #endif