1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2003-2004 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 * NOTE: 19 * 20 * These .Net APIs are a work in progress, currently being discussed and refined. 21 * If you plan to build an application based on these APIs, you may wish to 22 * statically link this code into your application, or otherwise distribute 23 * the DLL so that it installs into the same folder as your application 24 * (not into any common system area where it might interfere with other 25 * applications using a future completed version of these APIs). 26 * If you plan to do this, please be sure to inform us by sending email 27 * to bonjour@apple.com to let us know. 28 * You may want to discuss what you're doing on the Bonjour mailing 29 * list to see if others in similar positions have any suggestions for you: 30 * 31 * <http://lists.apple.com/bonjour-dev/> 32 * 33 */ 34 35 #pragma once 36 37 #include <dns_sd.h> 38 #include <vcclr.h> 39 #include <memory> 40 #include <winsock2.h> 41 42 using namespace System; 43 using namespace System::Net; 44 using namespace System::Runtime::InteropServices; 45 using namespace System::Threading; 46 using namespace System::Collections; 47 48 49 namespace Apple 50 { 51 namespace DNSSD 52 { 53 public __gc class ServiceRef; 54 55 public __value enum ServiceFlags : int 56 { 57 MoreComing = 1, 58 /* MoreComing indicates to a callback that at least one more result is 59 * queued and will be delivered following immediately after this one. 60 * Applications should not update their UI to display browse 61 * results when the MoreComing flag is set, because this would 62 * result in a great deal of ugly flickering on the screen. 63 * Applications should instead wait until until MoreComing is not set, 64 * and then update their UI. 65 * When MoreComing is not set, that doesn't mean there will be no more 66 * answers EVER, just that there are no more answers immediately 67 * available right now at this instant. If more answers become available 68 * in the future they will be delivered as usual. 69 */ 70 71 Add = 2, 72 Default = 4, 73 /* Flags for domain enumeration and browse/query reply callbacks. 74 * "Default" applies only to enumeration and is only valid in 75 * conjuction with "Add". An enumeration callback with the "Add" 76 * flag NOT set indicates a "Remove", i.e. the domain is no longer 77 * valid. 78 */ 79 80 NoAutoRename = 8, 81 /* Flag for specifying renaming behavior on name conflict when registering 82 * non-shared records. By default, name conflicts are automatically handled 83 * by renaming the service. NoAutoRename overrides this behavior - with this 84 * flag set, name conflicts will result in a callback. The NoAutorename flag 85 * is only valid if a name is explicitly specified when registering a service 86 * (i.e. the default name is not used.) 87 */ 88 89 Shared = 16, 90 Unique = 32, 91 /* Flag for registering individual records on a connected 92 * DNSServiceRef. Shared indicates that there may be multiple records 93 * with this name on the network (e.g. PTR records). Unique indicates that 94 the 95 * record's name is to be unique on the network (e.g. SRV records). 96 */ 97 98 BrowseDomains = 64, 99 RegistrationDomains = 128, 100 /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomain 101 s. 102 * BrowseDomains enumerates domains recommended for browsing, RegistrationDo 103 mains 104 * enumerates domains recommended for registration. 105 */ 106 }; 107 108 109 public __value enum ErrorCode : int 110 { 111 NoError = 0, 112 Unknown = -65537, 113 NoSuchName = -65538, 114 NoMemory = -65539, 115 BadParam = -65540, 116 BadReference = -65541, 117 BadState = -65542, 118 BadFlags = -65543, 119 Unsupported = -65544, 120 AlreadyRegistered = -65547, 121 NameConflict = -65548, 122 Invalid = -65549, 123 Incompatible = -65551, 124 BadinterfaceIndex = -65552 125 126 /* 127 * mDNS Error codes are in the range 128 * FFFE FF00 (-65792) to FFFE FFFF (-65537) 129 */ 130 }; 131 132 public __gc class DNSServiceException 133 : 134 public Exception 135 { 136 public: 137 138 DNSServiceException 139 ( 140 int err 141 ); 142 143 DNSServiceException 144 ( 145 String * message, 146 System::Exception * innerException 147 ); 148 149 int err; 150 }; 151 152 153 /* 154 * class RecordRef 155 * 156 * This is a thin MC++ class facade on top of a DNSRecordRef 157 */ 158 public __gc class RecordRef 159 { 160 public: 161 RecordRef()162 RecordRef() 163 { 164 m_impl = new RecordRefImpl; 165 m_impl->m_ref = NULL; 166 } 167 ~RecordRef()168 ~RecordRef() 169 { 170 delete m_impl; 171 } 172 173 __nogc class RecordRefImpl 174 { 175 public: 176 177 DNSRecordRef m_ref; 178 }; 179 180 RecordRefImpl * m_impl; 181 }; 182 183 184 /* 185 * class ServiceRef 186 * 187 * This is a thin MC++ class facade on top of a DNSServiceRef 188 */ 189 public __gc class ServiceRef : public IDisposable 190 { 191 public: 192 193 ServiceRef(Object * callback); 194 195 ~ServiceRef(); 196 197 /* 198 * This does an underlying DNSServiceRefDeallocate(). After 199 * calling Dispose, the ServiceRef is no longer usable. 200 */ 201 void 202 Dispose(); 203 204 /* 205 * Internal - Dispatch an EnumerateDomains callback 206 */ 207 void 208 EnumerateDomainsDispatch 209 ( 210 ServiceFlags flags, 211 int interfaceIndex, 212 ErrorCode errorCode, 213 String * replyDomain 214 ); 215 216 /* 217 * Internal - Dispatch a Register callback 218 */ 219 void 220 RegisterDispatch 221 ( 222 ServiceFlags flags, 223 ErrorCode errorCode, 224 String * name, 225 String * regtype, 226 String * domain 227 ); 228 229 /* 230 * Internal - Dispatch a Browse callback 231 */ 232 void 233 BrowseDispatch 234 ( 235 ServiceFlags flags, 236 int interfaceIndex, 237 ErrorCode errorCode, 238 String * serviceName, 239 String * regtype, 240 String * replyDomain 241 ); 242 243 /* 244 * Internal - Dispatch a Resolve callback 245 */ 246 void 247 ResolveDispatch 248 ( 249 ServiceFlags flags, 250 int interfaceIndex, 251 ErrorCode errorCode, 252 String * fullname, 253 String * hosttarget, 254 int port, 255 Byte txtRecord[] 256 ); 257 258 /* 259 * Internal - Dispatch a RegisterRecord callback 260 */ 261 void 262 RegisterRecordDispatch 263 ( 264 ServiceFlags flags, 265 ErrorCode errorCode, 266 RecordRef * record 267 ); 268 269 /* 270 * Internal - Dispatch a QueryRecord callback 271 */ 272 void 273 QueryRecordDispatch 274 ( 275 ServiceFlags flags, 276 int interfaceIndex, 277 ErrorCode errorCode, 278 String * fullname, 279 int rrtype, 280 int rrclass, 281 Byte rdata[], 282 int ttl 283 ); 284 285 /* 286 * Internal - A non managed class to wrap a DNSServiceRef 287 */ 288 __nogc class ServiceRefImpl 289 { 290 public: 291 292 ServiceRefImpl 293 ( 294 ServiceRef * outer 295 ); 296 297 ~ServiceRefImpl(); 298 299 /* 300 * Sets up events for threaded operation 301 */ 302 void 303 SetupEvents(); 304 305 /* 306 * Main processing thread 307 */ 308 void 309 ProcessingThread(); 310 311 /* 312 * Calls DNSServiceRefDeallocate() 313 */ 314 void 315 Dispose(); 316 317 /* 318 * Called from dnssd.dll 319 */ 320 static void DNSSD_API 321 EnumerateDomainsCallback 322 ( 323 DNSServiceRef sdRef, 324 DNSServiceFlags flags, 325 uint32_t interfaceIndex, 326 DNSServiceErrorType errorCode, 327 const char * replyDomain, 328 void * context 329 ); 330 331 static void DNSSD_API 332 RegisterCallback 333 ( 334 DNSServiceRef ref, 335 DNSServiceFlags flags, 336 DNSServiceErrorType errorCode, 337 const char * name, 338 const char * regtype, 339 const char * domain, 340 void * context 341 ); 342 343 static void DNSSD_API 344 BrowseCallback 345 ( 346 DNSServiceRef sdRef, 347 DNSServiceFlags flags, 348 uint32_t interfaceIndex, 349 DNSServiceErrorType errorCode, 350 const char * serviceName, 351 const char * regtype, 352 const char * replyDomain, 353 void * context 354 ); 355 356 static void DNSSD_API 357 ResolveCallback 358 ( 359 DNSServiceRef sdRef, 360 DNSServiceFlags flags, 361 uint32_t interfaceIndex, 362 DNSServiceErrorType errorCode, 363 const char * fullname, 364 const char * hosttarget, 365 uint16_t notAnIntPort, 366 uint16_t txtLen, 367 const char * txtRecord, 368 void * context 369 ); 370 371 static void DNSSD_API 372 RegisterRecordCallback 373 ( 374 DNSServiceRef sdRef, 375 DNSRecordRef RecordRef, 376 DNSServiceFlags flags, 377 DNSServiceErrorType errorCode, 378 void * context 379 ); 380 381 static void DNSSD_API 382 QueryRecordCallback 383 ( 384 DNSServiceRef DNSServiceRef, 385 DNSServiceFlags flags, 386 uint32_t interfaceIndex, 387 DNSServiceErrorType errorCode, 388 const char * fullname, 389 uint16_t rrtype, 390 uint16_t rrclass, 391 uint16_t rdlen, 392 const void * rdata, 393 uint32_t ttl, 394 void * context 395 ); 396 397 SOCKET m_socket; 398 HANDLE m_socketEvent; 399 HANDLE m_stopEvent; 400 DWORD m_threadId; 401 bool m_disposed; 402 DNSServiceRef m_ref; 403 gcroot<ServiceRef*> m_outer; 404 }; 405 406 void 407 StartThread(); 408 409 void 410 ProcessingThread(); 411 412 bool m_bDisposed; 413 Object * m_callback; 414 Thread * m_thread; 415 ServiceRefImpl * m_impl; 416 }; 417 418 /********************************************************************************************* 419 * 420 * TXT Record Construction Functions 421 * 422 *********************************************************************************************/ 423 424 /* 425 * A typical calling sequence for TXT record construction is something like: 426 * 427 * DNSService.TextRecord tr = new DNSService.TextRecord(1024); 428 * tr.SetValue(); 429 * tr.SetValue(); 430 * tr.SetValue(); 431 * ... 432 * DNSServiceRegister( ... tr.GetLength(), tr.GetBytes() ... ); 433 */ 434 435 436 /* TextRecord 437 * 438 * Opaque internal data type. 439 * Note: Represents a DNS-SD TXT record. 440 */ 441 442 443 /* TextRecord::TextRecord() 444 * 445 * Creates a new empty TextRecord . 446 * 447 */ 448 449 public __gc class TextRecord 450 { 451 public: 452 TextRecord()453 TextRecord() 454 { 455 m_impl = new TextRecordImpl(); 456 TXTRecordCreate(&m_impl->m_ref, 0, NULL); 457 } 458 ~TextRecord()459 ~TextRecord() 460 { 461 TXTRecordDeallocate(&m_impl->m_ref); 462 delete m_impl; 463 } 464 465 __nogc class TextRecordImpl 466 { 467 public: 468 469 TXTRecordRef m_ref; 470 }; 471 472 TextRecordImpl * m_impl; 473 474 475 /* SetValue() 476 * 477 * Adds a key (optionally with value) to a TextRecord. If the "key" already 478 * exists in the TextRecord, then the current value will be replaced with 479 * the new value. 480 * Keys may exist in four states with respect to a given TXT record: 481 * - Absent (key does not appear at all) 482 * - Present with no value ("key" appears alone) 483 * - Present with empty value ("key=" appears in TXT record) 484 * - Present with non-empty value ("key=value" appears in TXT record) 485 * For more details refer to "Data Syntax for DNS-SD TXT Records" in 486 * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt> 487 * 488 * key: A null-terminated string which only contains printable ASCII 489 * values (0x20-0x7E), excluding '=' (0x3D). Keys should be 490 * 14 characters or less (not counting the terminating null). 491 * 492 * value: Any binary value. For values that represent 493 * textual data, UTF-8 is STRONGLY recommended. 494 * For values that represent textual data, valueSize 495 * should NOT include the terminating null (if any) 496 * at the end of the string. 497 * If NULL, then "key" will be added with no value. 498 * If non-NULL but valueSize is zero, then "key=" will be 499 * added with empty value. 500 * 501 * exceptions: Throws kDNSServiceErr_Invalid if the "key" string contains 502 * illegal characters. 503 * Throws kDNSServiceErr_NoMemory if adding this key would 504 * exceed the available storage. 505 */ 506 507 void 508 SetValue 509 ( 510 String * key, 511 Byte value[] /* may be NULL */ 512 ); 513 514 515 /* RemoveValue() 516 * 517 * Removes a key from a TextRecord. The "key" must be an 518 * ASCII string which exists in the TextRecord. 519 * 520 * key: A key name which exists in the TextRecord. 521 * 522 * exceptions: Throws kDNSServiceErr_NoSuchKey if the "key" does not 523 * exist in the TextRecord. 524 * 525 */ 526 527 void 528 RemoveValue 529 ( 530 String * key 531 ); 532 533 534 /* GetLength() 535 * 536 * Allows you to determine the length of the raw bytes within a TextRecord. 537 * 538 * return value : Returns the size of the raw bytes inside a TextRecord 539 * which you can pass directly to DNSServiceRegister() or 540 * to DNSServiceUpdateRecord(). 541 * Returns 0 if the TextRecord is empty. 542 * 543 */ 544 545 int 546 GetLength 547 ( 548 ); 549 550 551 /* GetBytes() 552 * 553 * Allows you to retrieve a pointer to the raw bytes within a TextRecord. 554 * 555 * return value: Returns a pointer to the bytes inside the TextRecord 556 * which you can pass directly to DNSServiceRegister() or 557 * to DNSServiceUpdateRecord(). 558 * 559 */ 560 561 Byte 562 GetBytes 563 ( 564 ) __gc[]; 565 566 567 /********************************************************************************************* 568 * 569 * TXT Record Parsing Functions 570 * 571 *********************************************************************************************/ 572 573 /* 574 * A typical calling sequence for TXT record parsing is something like: 575 * 576 * Receive TXT record data in DNSServiceResolve() callback 577 * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something 578 * val1ptr = DNSService.TextService.GetValue(txtRecord, "key1", &len1); 579 * val2ptr = DNSService.TextService.GetValue(txtRecord, "key2", &len2); 580 * ... 581 * return; 582 * 583 */ 584 585 /* ContainsKey() 586 * 587 * Allows you to determine if a given TXT Record contains a specified key. 588 * 589 * txtRecord: Pointer to the received TXT Record bytes. 590 * 591 * key: A null-terminated ASCII string containing the key name. 592 * 593 * return value: Returns 1 if the TXT Record contains the specified key. 594 * Otherwise, it returns 0. 595 * 596 */ 597 598 static public bool 599 ContainsKey 600 ( 601 Byte txtRecord[], 602 String * key 603 ); 604 605 606 /* GetValueBytes() 607 * 608 * Allows you to retrieve the value for a given key from a TXT Record. 609 * 610 * txtRecord: Pointer to the received TXT Record bytes. 611 * 612 * key: A null-terminated ASCII string containing the key name. 613 * 614 * return value: Returns NULL if the key does not exist in this TXT record, 615 * or exists with no value (to differentiate between 616 * these two cases use ContainsKey()). 617 * Returns byte array 618 * if the key exists with empty or non-empty value. 619 * For empty value, length of byte array will be zero. 620 * For non-empty value, it will be the length of value data. 621 */ 622 623 static public Byte 624 GetValueBytes 625 ( 626 Byte txtRecord[], 627 String * key 628 ) __gc[]; 629 630 631 /* GetCount() 632 * 633 * Returns the number of keys stored in the TXT Record. The count 634 * can be used with TXTRecordGetItemAtIndex() to iterate through the keys. 635 * 636 * txtRecord: Pointer to the received TXT Record bytes. 637 * 638 * return value: Returns the total number of keys in the TXT Record. 639 * 640 */ 641 642 static public int 643 GetCount 644 ( 645 Byte txtRecord[] 646 ); 647 648 649 /* GetItemAtIndex() 650 * 651 * Allows you to retrieve a key name and value pointer, given an index into 652 * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1. 653 * It's also possible to iterate through keys in a TXT record by simply 654 * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero 655 * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid. 656 * 657 * On return: 658 * For keys with no value, *value is set to NULL and *valueLen is zero. 659 * For keys with empty value, *value is non-NULL and *valueLen is zero. 660 * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero. 661 * 662 * txtRecord: Pointer to the received TXT Record bytes. 663 * 664 * index: An index into the TXT Record. 665 * 666 * key: A string buffer used to store the key name. 667 * On return, the buffer contains a string 668 * giving the key name. DNS-SD TXT keys are usually 669 * 14 characters or less. 670 * 671 * return value: Record bytes that holds the value data. 672 * 673 * exceptions: Throws kDNSServiceErr_Invalid if index is greater than 674 * GetCount()-1. 675 */ 676 677 static public Byte 678 GetItemAtIndex 679 ( 680 Byte txtRecord[], 681 int index, 682 [Out] String ** key 683 ) __gc[]; 684 }; 685 686 687 public __abstract __gc class DNSService 688 { 689 public: 690 691 /********************************************************************************************* 692 * 693 * Domain Enumeration 694 * 695 *********************************************************************************************/ 696 697 /* DNSServiceEnumerateDomains() 698 * 699 * Asynchronously enumerate domains available for browsing and registration. 700 * Currently, the only domain returned is "local.", but other domains will be returned in future. 701 * 702 * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains 703 * are to be found. 704 * 705 * 706 * EnumerateDomainsReply Delegate 707 * 708 * This Delegate is invoked upon a reply from an EnumerateDomains call. 709 * 710 * sdRef: The DNSServiceRef initialized by DNSServiceEnumerateDomains(). 711 * 712 * flags: Possible values are: 713 * MoreComing 714 * Add 715 * Default 716 * 717 * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given 718 * interface is determined via the if_nametoindex() family of calls.) 719 * 720 * errorCode: Will be NoError (0) on success, otherwise indicates 721 * the failure that occurred (other parameters are undefined if errorCode is nonzero). 722 * 723 * replyDomain: The name of the domain. 724 * 725 */ 726 727 __delegate void 728 EnumerateDomainsReply 729 ( 730 ServiceRef * sdRef, 731 ServiceFlags flags, 732 int interfaceIndex, 733 ErrorCode errorCode, 734 String * replyDomain 735 ); 736 737 /* DNSServiceEnumerateDomains() Parameters: 738 * 739 * 740 * flags: Possible values are: 741 * BrowseDomains to enumerate domains recommended for browsing. 742 * RegistrationDomains to enumerate domains recommended 743 * for registration. 744 * 745 * interfaceIndex: If non-zero, specifies the interface on which to look for domains. 746 * (the index for a given interface is determined via the if_nametoindex() 747 * family of calls.) Most applications will pass 0 to enumerate domains on 748 * all interfaces. 749 * 750 * callback: The delegate to be called when a domain is found or the call asynchronously 751 * fails. 752 * 753 * 754 * return value: Returns initialize ServiceRef on succeses (any subsequent, asynchronous 755 * errors are delivered to the delegate), otherwise throws an exception indicating 756 * the error that occurred (the callback is not invoked and the ServiceRef 757 * is not initialized.) 758 */ 759 760 static public ServiceRef* 761 EnumerateDomains 762 ( 763 int flags, 764 int interfaceIndex, 765 EnumerateDomainsReply * callback 766 ); 767 768 /********************************************************************************************* 769 * 770 * Service Registration 771 * 772 *********************************************************************************************/ 773 774 /* Register a service that is discovered via Browse() and Resolve() calls. 775 * 776 * RegisterReply() Callback Parameters: 777 * 778 * sdRef: The ServiceRef initialized by Register(). 779 * 780 * flags: Currently unused, reserved for future use. 781 * 782 * errorCode: Will be NoError on success, otherwise will 783 * indicate the failure that occurred (including name conflicts, if the 784 * NoAutoRename flag was passed to the 785 * callout.) Other parameters are undefined if errorCode is nonzero. 786 * 787 * name: The service name registered (if the application did not specify a name in 788 * DNSServiceRegister(), this indicates what name was automatically chosen). 789 * 790 * regtype: The type of service registered, as it was passed to the callout. 791 * 792 * domain: The domain on which the service was registered (if the application did not 793 * specify a domain in Register(), this indicates the default domain 794 * on which the service was registered). 795 * 796 */ 797 798 __delegate void 799 RegisterReply 800 ( 801 ServiceRef * sdRef, 802 ServiceFlags flags, 803 ErrorCode errorCode, 804 String * name, 805 String * regtype, 806 String * domain 807 ); 808 809 /* Register() Parameters: 810 * 811 * flags: Indicates the renaming behavior on name conflict (most applications 812 * will pass 0). See flag definitions above for details. 813 * 814 * interfaceIndex: If non-zero, specifies the interface on which to register the service 815 * (the index for a given interface is determined via the if_nametoindex() 816 * family of calls.) Most applications will pass 0 to register on all 817 * available interfaces. Pass -1 to register a service only on the local 818 * machine (service will not be visible to remote hosts.) 819 * 820 * name: If non-NULL, specifies the service name to be registered. 821 * Most applications will not specify a name, in which case the 822 * computer name is used (this name is communicated to the client via 823 * the callback). 824 * 825 * regtype: The service type followed by the protocol, separated by a dot 826 * (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". 827 * New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html. 828 * 829 * domain: If non-NULL, specifies the domain on which to advertise the service. 830 * Most applications will not specify a domain, instead automatically 831 * registering in the default domain(s). 832 * 833 * host: If non-NULL, specifies the SRV target host name. Most applications 834 * will not specify a host, instead automatically using the machine's 835 * default host name(s). Note that specifying a non-NULL host does NOT 836 * create an address record for that host - the application is responsible 837 * for ensuring that the appropriate address record exists, or creating it 838 * via DNSServiceRegisterRecord(). 839 * 840 * port: The port, in host byte order, on which the service accepts connections. 841 * Pass 0 for a "placeholder" service (i.e. a service that will not be discovered 842 * by browsing, but will cause a name conflict if another client tries to 843 * register that same name). Most clients will not use placeholder services. 844 * 845 * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord 846 * MUST be a properly formatted DNS TXT record, i.e. <length byte> <data> 847 * <length byte> <data> ... 848 * 849 * callback: The delegate to be called when the registration completes or asynchronously 850 * fails. The client MAY pass NULL for the callback - The client will NOT be notified 851 * of the default values picked on its behalf, and the client will NOT be notified of any 852 * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration 853 * of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL. 854 * The client may still deregister the service at any time via DNSServiceRefDeallocate(). 855 * 856 * return value: Returns initialize ServiceRef (any subsequent, asynchronous 857 * errors are delivered to the callback), otherwise throws an exception indicating 858 * the error that occurred (the callback is never invoked and the DNSServiceRef 859 * is not initialized.) 860 * 861 */ 862 static public ServiceRef* 863 Register 864 ( 865 int flags, 866 int interfaceIndex, 867 String * name, 868 String * regtype, 869 String * domain, 870 String * host, 871 int port, 872 Byte txtRecord[], 873 RegisterReply * callback 874 ); 875 876 /* AddRecord() 877 * 878 * Add a record to a registered service. The name of the record will be the same as the 879 * registered service's name. 880 * The record can later be updated or deregistered by passing the RecordRef initialized 881 * by this function to UpdateRecord() or RemoveRecord(). 882 * 883 * 884 * Parameters; 885 * 886 * sdRef: A ServiceRef initialized by Register(). 887 * 888 * RecordRef: A pointer to an uninitialized RecordRef. Upon succesfull completion of this 889 * call, this ref may be passed to UpdateRecord() or RemoveRecord(). 890 * If the above ServiceRef is disposed, RecordRef is also 891 * invalidated and may not be used further. 892 * 893 * flags: Currently ignored, reserved for future use. 894 * 895 * rrtype: The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h. 896 * 897 * rdata: The raw rdata to be contained in the added resource record. 898 * 899 * ttl: The time to live of the resource record, in seconds. 900 * 901 * return value: Returns initialized RecordRef, otherwise throws 902 * an exception indicating the error that occurred (the RecordRef is not initialized). 903 */ 904 905 static public RecordRef* 906 AddRecord 907 ( 908 ServiceRef * sref, 909 int flags, 910 int rrtype, 911 Byte rdata[], 912 int ttl 913 ); 914 915 /* UpdateRecord 916 * 917 * Update a registered resource record. The record must either be: 918 * - The primary txt record of a service registered via Register() 919 * - A record added to a registered service via AddRecord() 920 * - An individual record registered by RegisterRecord() 921 * 922 * 923 * Parameters: 924 * 925 * sdRef: A ServiceRef that was initialized by Register() 926 * or CreateConnection(). 927 * 928 * RecordRef: A RecordRef initialized by AddRecord, or NULL to update the 929 * service's primary txt record. 930 * 931 * flags: Currently ignored, reserved for future use. 932 * 933 * rdata: The new rdata to be contained in the updated resource record. 934 * 935 * ttl: The time to live of the updated resource record, in seconds. 936 * 937 * return value: No return value on success, otherwise throws an exception 938 * indicating the error that occurred. 939 */ 940 static public void 941 UpdateRecord 942 ( 943 ServiceRef * sref, 944 RecordRef * record, 945 int flags, 946 Byte rdata[], 947 int ttl 948 ); 949 950 /* RemoveRecord 951 * 952 * Remove a record previously added to a service record set via AddRecord(), or deregister 953 * an record registered individually via RegisterRecord(). 954 * 955 * Parameters: 956 * 957 * sdRef: A ServiceRef initialized by Register() (if the 958 * record being removed was registered via AddRecord()) or by 959 * CreateConnection() (if the record being removed was registered via 960 * RegisterRecord()). 961 * 962 * recordRef: A RecordRef initialized by a successful call to AddRecord() 963 * or RegisterRecord(). 964 * 965 * flags: Currently ignored, reserved for future use. 966 * 967 * return value: Nothing on success, otherwise throws an 968 * exception indicating the error that occurred. 969 */ 970 971 static public void 972 RemoveRecord 973 ( 974 ServiceRef * sref, 975 RecordRef * record, 976 int flags 977 ); 978 979 /********************************************************************************************* 980 * 981 * Service Discovery 982 * 983 *********************************************************************************************/ 984 985 /* Browse for instances of a service. 986 * 987 * 988 * BrowseReply() Parameters: 989 * 990 * sdRef: The DNSServiceRef initialized by Browse(). 991 * 992 * flags: Possible values are MoreComing and Add. 993 * See flag definitions for details. 994 * 995 * interfaceIndex: The interface on which the service is advertised. This index should 996 * be passed to Resolve() when resolving the service. 997 * 998 * errorCode: Will be NoError (0) on success, otherwise will 999 * indicate the failure that occurred. Other parameters are undefined if 1000 * the errorCode is nonzero. 1001 * 1002 * serviceName: The service name discovered. 1003 * 1004 * regtype: The service type, as passed in to Browse(). 1005 * 1006 * domain: The domain on which the service was discovered (if the application did not 1007 * specify a domain in Browse(), this indicates the domain on which the 1008 * service was discovered.) 1009 * 1010 */ 1011 1012 __delegate void 1013 BrowseReply 1014 ( 1015 ServiceRef * sdRef, 1016 ServiceFlags flags, 1017 int interfaceIndex, 1018 ErrorCode errorCode, 1019 String * name, 1020 String * type, 1021 String * domain 1022 ); 1023 1024 /* DNSServiceBrowse() Parameters: 1025 * 1026 * sdRef: A pointer to an uninitialized ServiceRef. Call ServiceRef.Dispose() 1027 * to terminate the browse. 1028 * 1029 * flags: Currently ignored, reserved for future use. 1030 * 1031 * interfaceIndex: If non-zero, specifies the interface on which to browse for services 1032 * (the index for a given interface is determined via the if_nametoindex() 1033 * family of calls.) Most applications will pass 0 to browse on all available 1034 * interfaces. Pass -1 to only browse for services provided on the local host. 1035 * 1036 * regtype: The service type being browsed for followed by the protocol, separated by a 1037 * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". 1038 * 1039 * domain: If non-NULL, specifies the domain on which to browse for services. 1040 * Most applications will not specify a domain, instead browsing on the 1041 * default domain(s). 1042 * 1043 * callback: The delegate to be called when an instance of the service being browsed for 1044 * is found, or if the call asynchronously fails. 1045 * 1046 * return value: Returns initialized ServiceRef on succeses (any subsequent, asynchronous 1047 * errors are delivered to the callback), otherwise throws an exception indicating 1048 * the error that occurred (the callback is not invoked and the ServiceRef 1049 * is not initialized.) 1050 */ 1051 1052 static public ServiceRef* 1053 Browse 1054 ( 1055 int flags, 1056 int interfaceIndex, 1057 String * regtype, 1058 String * domain, 1059 BrowseReply * callback 1060 ); 1061 1062 /* ResolveReply() Parameters: 1063 * 1064 * Resolve a service name discovered via Browse() to a target host name, port number, and 1065 * txt record. 1066 * 1067 * Note: Applications should NOT use Resolve() solely for txt record monitoring - use 1068 * QueryRecord() instead, as it is more efficient for this task. 1069 * 1070 * Note: When the desired results have been returned, the client MUST terminate the resolve by calling 1071 * ServiceRef.Dispose(). 1072 * 1073 * Note: Resolve() behaves correctly for typical services that have a single SRV record and 1074 * a single TXT record (the TXT record may be empty.) To resolve non-standard services with multiple 1075 * SRV or TXT records, QueryRecord() should be used. 1076 * 1077 * ResolveReply Callback Parameters: 1078 * 1079 * sdRef: The DNSServiceRef initialized by Resolve(). 1080 * 1081 * flags: Currently unused, reserved for future use. 1082 * 1083 * interfaceIndex: The interface on which the service was resolved. 1084 * 1085 * errorCode: Will be NoError (0) on success, otherwise will 1086 * indicate the failure that occurred. Other parameters are undefined if 1087 * the errorCode is nonzero. 1088 * 1089 * fullname: The full service domain name, in the form <servicename>.<protocol>.<domain>. 1090 * (Any literal dots (".") are escaped with a backslash ("\."), and literal 1091 * backslashes are escaped with a second backslash ("\\"), e.g. a web server 1092 * named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local."). 1093 * This is the appropriate format to pass to standard system DNS APIs such as 1094 * res_query(), or to the special-purpose functions included in this API that 1095 * take fullname parameters. 1096 * 1097 * hosttarget: The target hostname of the machine providing the service. This name can 1098 * be passed to functions like gethostbyname() to identify the host's IP address. 1099 * 1100 * port: The port, in host byte order, on which connections are accepted for this service. 1101 * 1102 * txtRecord: The service's primary txt record, in standard txt record format. 1103 * 1104 */ 1105 1106 __delegate void 1107 ResolveReply 1108 ( 1109 ServiceRef * sdRef, 1110 ServiceFlags flags, 1111 int interfaceIndex, 1112 ErrorCode errorCode, 1113 String * fullName, 1114 String * hostName, 1115 int port, 1116 Byte txtRecord[] 1117 ); 1118 1119 /* Resolve() Parameters 1120 * 1121 * flags: Currently ignored, reserved for future use. 1122 * 1123 * interfaceIndex: The interface on which to resolve the service. The client should 1124 * pass the interface on which the servicename was discovered, i.e. 1125 * the interfaceIndex passed to the DNSServiceBrowseReply callback, 1126 * or 0 to resolve the named service on all available interfaces. 1127 * 1128 * name: The servicename to be resolved. 1129 * 1130 * regtype: The service type being resolved followed by the protocol, separated by a 1131 * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". 1132 * 1133 * domain: The domain on which the service is registered, i.e. the domain passed 1134 * to the DNSServiceBrowseReply callback. 1135 * 1136 * callback: The delegate to be called when a result is found, or if the call 1137 * asynchronously fails. 1138 * 1139 * 1140 * return value: Returns initialized ServiceRef on succeses (any subsequent, asynchronous 1141 * errors are delivered to the callback), otherwise throws an exception indicating 1142 * the error that occurred (the callback is never invoked and the DNSServiceRef 1143 * is not initialized.) 1144 */ 1145 1146 static public ServiceRef* 1147 Resolve 1148 ( 1149 int flags, 1150 int interfaceIndex, 1151 String * name, 1152 String * regtype, 1153 String * domain, 1154 ResolveReply * callback 1155 ); 1156 1157 /********************************************************************************************* 1158 * 1159 * Special Purpose Calls (most applications will not use these) 1160 * 1161 *********************************************************************************************/ 1162 1163 /* CreateConnection/RegisterRecord 1164 * 1165 * Register an individual resource record on a connected ServiceRef. 1166 * 1167 * Note that name conflicts occurring for records registered via this call must be handled 1168 * by the client in the callback. 1169 * 1170 * 1171 * RecordReply() parameters: 1172 * 1173 * sdRef: The connected ServiceRef initialized by 1174 * CreateConnection(). 1175 * 1176 * RecordRef: The RecordRef initialized by RegisterRecord(). If the above 1177 * ServiceRef.Dispose is called, this RecordRef is 1178 * invalidated, and may not be used further. 1179 * 1180 * flags: Currently unused, reserved for future use. 1181 * 1182 * errorCode: Will be NoError on success, otherwise will 1183 * indicate the failure that occurred (including name conflicts.) 1184 * Other parameters are undefined if errorCode is nonzero. 1185 * 1186 */ 1187 1188 __delegate void 1189 RegisterRecordReply 1190 ( 1191 ServiceRef * sdRef, 1192 ServiceFlags flags, 1193 ErrorCode errorCode, 1194 RecordRef * record 1195 ); 1196 1197 /* CreateConnection() 1198 * 1199 * Create a connection to the daemon allowing efficient registration of 1200 * multiple individual records. 1201 * 1202 * 1203 * Parameters: 1204 * 1205 * callback: The delegate to be called when a result is found, or if the call 1206 * asynchronously fails (e.g. because of a name conflict.) 1207 * 1208 * return value: Returns initialize ServiceRef on success, otherwise throws 1209 * an exception indicating the specific failure that occurred (in which 1210 * case the ServiceRef is not initialized). 1211 */ 1212 1213 static public ServiceRef* 1214 CreateConnection 1215 ( 1216 RegisterRecordReply * callback 1217 ); 1218 1219 1220 /* RegisterRecord() Parameters: 1221 * 1222 * sdRef: A ServiceRef initialized by CreateConnection(). 1223 * 1224 * RecordRef: A pointer to an uninitialized RecordRef. Upon succesfull completion of this 1225 * call, this ref may be passed to UpdateRecord() or RemoveRecord(). 1226 * (To deregister ALL records registered on a single connected ServiceRef 1227 * and deallocate each of their corresponding RecordRefs, call 1228 * ServiceRef.Dispose()). 1229 * 1230 * flags: Possible values are Shared or Unique 1231 * (see flag type definitions for details). 1232 * 1233 * interfaceIndex: If non-zero, specifies the interface on which to register the record 1234 * (the index for a given interface is determined via the if_nametoindex() 1235 * family of calls.) Passing 0 causes the record to be registered on all interfaces. 1236 * Passing -1 causes the record to only be visible on the local host. 1237 * 1238 * fullname: The full domain name of the resource record. 1239 * 1240 * rrtype: The numerical type of the resource record (e.g. PTR, SRV, etc), as defined 1241 * in nameser.h. 1242 * 1243 * rrclass: The class of the resource record, as defined in nameser.h (usually 1 for the 1244 * Internet class). 1245 * 1246 * rdata: A pointer to the raw rdata, as it is to appear in the DNS record. 1247 * 1248 * ttl: The time to live of the resource record, in seconds. 1249 * 1250 * 1251 * return value: Returns initialize RecordRef on succeses (any subsequent, asynchronous 1252 * errors are delivered to the callback), otherwise throws an exception indicating 1253 * the error that occurred (the callback is never invoked and the RecordRef is 1254 * not initialized.) 1255 */ 1256 static public RecordRef* 1257 RegisterRecord 1258 ( 1259 ServiceRef * sdRef, 1260 ServiceFlags flags, 1261 int interfaceIndex, 1262 String * fullname, 1263 int rrtype, 1264 int rrclass, 1265 Byte rdata[], 1266 int ttl 1267 ); 1268 1269 1270 /* DNSServiceQueryRecord 1271 * 1272 * Query for an arbitrary DNS record. 1273 * 1274 * 1275 * QueryRecordReply() Delegate Parameters: 1276 * 1277 * sdRef: The ServiceRef initialized by QueryRecord(). 1278 * 1279 * flags: Possible values are MoreComing and 1280 * Add. The Add flag is NOT set for PTR records 1281 * with a ttl of 0, i.e. "Remove" events. 1282 * 1283 * interfaceIndex: The interface on which the query was resolved (the index for a given 1284 * interface is determined via the if_nametoindex() family of calls). 1285 * 1286 * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will 1287 * indicate the failure that occurred. Other parameters are undefined if 1288 * errorCode is nonzero. 1289 * 1290 * fullname: The resource record's full domain name. 1291 * 1292 * rrtype: The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. 1293 * 1294 * rrclass: The class of the resource record, as defined in nameser.h (usually 1). 1295 * 1296 * rdata: The raw rdata of the resource record. 1297 * 1298 * ttl: The resource record's time to live, in seconds. 1299 * 1300 */ 1301 1302 __delegate void 1303 QueryRecordReply 1304 ( 1305 ServiceRef * sdRef, 1306 ServiceFlags flags, 1307 int interfaceIndex, 1308 ErrorCode errorCode, 1309 String * fullName, 1310 int rrtype, 1311 int rrclass, 1312 Byte rdata[], 1313 int ttl 1314 ); 1315 1316 /* QueryRecord() Parameters: 1317 * 1318 * flags: Pass LongLivedQuery to create a "long-lived" unicast 1319 * query in a non-local domain. Without setting this flag, unicast queries 1320 * will be one-shot - that is, only answers available at the time of the call 1321 * will be returned. By setting this flag, answers (including Add and Remove 1322 * events) that become available after the initial call is made will generate 1323 * callbacks. This flag has no effect on link-local multicast queries. 1324 * 1325 * interfaceIndex: If non-zero, specifies the interface on which to issue the query 1326 * (the index for a given interface is determined via the if_nametoindex() 1327 * family of calls.) Passing 0 causes the name to be queried for on all 1328 * interfaces. Passing -1 causes the name to be queried for only on the 1329 * local host. 1330 * 1331 * fullname: The full domain name of the resource record to be queried for. 1332 * 1333 * rrtype: The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) 1334 * as defined in nameser.h. 1335 * 1336 * rrclass: The class of the resource record, as defined in nameser.h 1337 * (usually 1 for the Internet class). 1338 * 1339 * callback: The delegate to be called when a result is found, or if the call 1340 * asynchronously fails. 1341 * 1342 * 1343 * return value: Returns initialized ServiceRef on succeses (any subsequent, asynchronous 1344 * errors are delivered to the callback), otherwise throws an exception indicating 1345 * the error that occurred (the callback is never invoked and the ServiceRef 1346 * is not initialized.) 1347 */ 1348 1349 static public ServiceRef* 1350 QueryRecord 1351 ( 1352 ServiceFlags flags, 1353 int interfaceIndex, 1354 String * fullname, 1355 int rrtype, 1356 int rrclass, 1357 QueryRecordReply * callback 1358 ); 1359 1360 /* ReconfirmRecord 1361 * 1362 * Instruct the daemon to verify the validity of a resource record that appears to 1363 * be out of date (e.g. because tcp connection to a service's target failed.) 1364 * Causes the record to be flushed from the daemon's cache (as well as all other 1365 * daemons' caches on the network) if the record is determined to be invalid. 1366 * 1367 * Parameters: 1368 * 1369 * flags: Currently unused, reserved for future use. 1370 * 1371 * fullname: The resource record's full domain name. 1372 * 1373 * rrtype: The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. 1374 * 1375 * rrclass: The class of the resource record, as defined in nameser.h (usually 1). 1376 * 1377 * rdata: The raw rdata of the resource record. 1378 * 1379 */ 1380 static public void 1381 ReconfirmRecord 1382 ( 1383 ServiceFlags flags, 1384 int interfaceIndex, 1385 String * fullname, 1386 int rrtype, 1387 int rrclass, 1388 Byte rdata[] 1389 ); 1390 }; 1391 } 1392 } 1393