summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdns_sd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdns_sd')
-rw-r--r--usr/src/lib/libdns_sd/Makefile59
-rw-r--r--usr/src/lib/libdns_sd/Makefile.com51
-rw-r--r--usr/src/lib/libdns_sd/README65
-rw-r--r--usr/src/lib/libdns_sd/amd64/Makefile30
-rw-r--r--usr/src/lib/libdns_sd/common/dns_sd.h1725
-rw-r--r--usr/src/lib/libdns_sd/common/dnssd_clientlib.c373
-rw-r--r--usr/src/lib/libdns_sd/common/dnssd_clientstub.c1249
-rw-r--r--usr/src/lib/libdns_sd/common/dnssd_ipc.c135
-rw-r--r--usr/src/lib/libdns_sd/common/dnssd_ipc.h253
-rw-r--r--usr/src/lib/libdns_sd/common/llib-ldns_sd32
-rw-r--r--usr/src/lib/libdns_sd/common/mapfile-vers56
-rw-r--r--usr/src/lib/libdns_sd/i386/Makefile28
-rw-r--r--usr/src/lib/libdns_sd/java/Makefile47
-rw-r--r--usr/src/lib/libdns_sd/java/Makefile.com57
-rw-r--r--usr/src/lib/libdns_sd/java/amd64/Makefile32
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/Makefile47
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/Makefile.com31
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java51
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java88
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java68
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java897
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java76
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java79
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java77
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java52
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java75
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile150
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java71
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java64
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java49
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java71
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java313
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java400
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest3
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java336
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest3
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java126
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java119
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java111
-rw-r--r--usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java109
-rw-r--r--usr/src/lib/libdns_sd/java/common/JNISupport.c1107
-rw-r--r--usr/src/lib/libdns_sd/java/common/mapfile-vers48
-rw-r--r--usr/src/lib/libdns_sd/java/i386/Makefile35
-rw-r--r--usr/src/lib/libdns_sd/java/sparc/Makefile35
-rw-r--r--usr/src/lib/libdns_sd/java/sparcv9/Makefile32
-rw-r--r--usr/src/lib/libdns_sd/sparc/Makefile28
-rw-r--r--usr/src/lib/libdns_sd/sparcv9/Makefile35
47 files changed, 8978 insertions, 0 deletions
diff --git a/usr/src/lib/libdns_sd/Makefile b/usr/src/lib/libdns_sd/Makefile
new file mode 100644
index 0000000000..21a4e1aa1d
--- /dev/null
+++ b/usr/src/lib/libdns_sd/Makefile
@@ -0,0 +1,59 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.lib
+
+HDR = dns_sd.h
+HDRDIR = common
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all install: install_h $(SUBDIRS) .WAIT java
+
+clean clobber: $(SUBDIRS)
+
+ROOTHDRDIR= $(ROOT)/usr/include
+ROOTHDRS= $(HDR:%=$(ROOTHDRDIR)/%)
+
+install_h: $(ROOTHDRS)
+
+check:
+
+lint: $(SUBDIRS)
+
+$(SUBDIRS) java: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/lib/libdns_sd/Makefile.com b/usr/src/lib/libdns_sd/Makefile.com
new file mode 100644
index 0000000000..4b6fe00f9b
--- /dev/null
+++ b/usr/src/lib/libdns_sd/Makefile.com
@@ -0,0 +1,51 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+LIBRARY = libdns_sd.a
+VERS = .1
+OBJECTS = dnssd_clientlib.o dnssd_clientstub.o dnssd_ipc.o
+
+include ../../Makefile.lib
+
+LIBS = $(DYNLIB) $(LINTLIB)
+$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
+
+SRCDIR = ../common
+
+LDLIBS += -lsocket -lc
+
+C99MODE = $(C99_ENABLE)
+CFLAGS += -erroff=E_ASSIGNMENT_TYPE_MISMATCH
+CPPFLAGS += -I$(SRCDIR) -DNOT_HAVE_SA_LEN
+
+.PARALLEL = $(OBJECTS)
+.KEEP_STATE:
+
+lint: lintcheck
+
+all: $(LIBS)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/libdns_sd/README b/usr/src/lib/libdns_sd/README
new file mode 100644
index 0000000000..a7deae9108
--- /dev/null
+++ b/usr/src/lib/libdns_sd/README
@@ -0,0 +1,65 @@
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+Multicast DNS and Service Discovery support in Solaris using the
+Apple Bonjour source code (v107.6). Apple Bonjour source can be
+downloaded from:
+ http://developer.apple.com/networking/bonjour/download/
+The following components are integrated from the Apple Bonjour
+source in Solaris:
+ libdns_sd: usr/src/lib/libdns_sd <dns_sd.h>
+ libjdns_sd: usr/src/lib/libdns_sd/java/common
+ dnssd.jar: usr/src/lib/libdns_sd/java/com (incl. examples)
+ mdnsd: usr/src/cmd/cmd-inet/usr.lib/mdnsd
+ dns-sd: usr/src/cmd/cmd-inet/usr.bin/dns-sd.c
+
+Following fixes have been made to the Apple Bonjour source
+integrated in Solaris:
+* 64-bit support by adding pad bytes in ipc_msg_hdr_struct
+* 64-bit support in libjdns_sd, dnssd.jar (JNISupport.c, DNSSD.java)
+* mdnsd switches to user 'noaccess' and not 'nobody' after init
+* Fixes to support IPv6 (mDNSPosix.c, mDNSUNP.c)
+* Fix error raised when uDNS.c is compiled with Sun Studio compiler
+* Fix in dnssd_clientstub.c to not check errno when recvmsg returns 0
+* mDNSDebug.c modified to not send msgs directly to console when
+ syslog call returns an error. Logs the messages at LOG_INFO level
+ and not LOG_ERR
+
+In addition the project introduces the following changes:
+* A new nss_mdns module is introduced to use Multicast DNS (mdns)
+ for resolving link-local hostnames and is located at:
+ usr/src/lib/nsswitch/mdns
+* snoop updated to decode mDNS packets
+* updated /etc/services to include mdns
+* <netinet/in.h> updated to include mdns
+* svc:/network/dns/multicast:default introduced to manage mDNS daemon
+* solaris.smf.manage.mdns & solaris.smf.value.mdns authorizations
+ to modify nss_mdns configuration in svc:/network/dns/multicast:default
+ Both authorizations added in network management execution profile.
+* Default nsswitch.dns includes mdns as source for hosts & ipnodes
+* nscd daemon updated to support mdns
+* SUNWdsdu and SUNWdsdr packages deliver all the new mDNS
+ service discovery components.
diff --git a/usr/src/lib/libdns_sd/amd64/Makefile b/usr/src/lib/libdns_sd/amd64/Makefile
new file mode 100644
index 0000000000..2fa1329472
--- /dev/null
+++ b/usr/src/lib/libdns_sd/amd64/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+CFLAGS64 += -erroff=E_ASSIGNMENT_TYPE_MISMATCH
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/libdns_sd/common/dns_sd.h b/usr/src/lib/libdns_sd/common/dns_sd.h
new file mode 100644
index 0000000000..7ffe6da198
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/dns_sd.h
@@ -0,0 +1,1725 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef _DNS_SD_H
+#define _DNS_SD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* standard calling convention under Win32 is __stdcall */
+/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
+/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
+#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
+#define DNSSD_API __stdcall
+#else
+#define DNSSD_API
+#endif
+
+/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
+#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
+#include <sys/types.h>
+
+/* Likewise, on Sun, standard integer types are in sys/types.h */
+#elif defined(__sun__)
+#include <sys/types.h>
+
+/* EFI does not have stdint.h, or anything else equivalent */
+#elif defined(EFI32) || defined(EFI64)
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+
+/* Windows has its own differences */
+#elif defined(_WIN32)
+#include <windows.h>
+#define _UNUSED
+#define bzero(a, b) memset(a, 0, b)
+#ifndef _MSL_STDINT_H
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+#endif
+
+/* All other Posix platforms use stdint.h */
+#else
+#include <stdint.h>
+#include <strings.h>
+#endif
+
+/* DNSServiceRef, DNSRecordRef
+ *
+ * Opaque internal data types.
+ * Note: client is responsible for serializing access to these structures if
+ * they are shared between concurrent threads.
+ */
+
+typedef struct _DNSServiceRef_t *DNSServiceRef;
+typedef struct _DNSRecordRef_t *DNSRecordRef;
+
+/* General flags used in functions defined below */
+enum
+ {
+ kDNSServiceFlagsMoreComing = 0x1,
+ /* MoreComing indicates to a callback that at least one more result is
+ * queued and will be delivered following immediately after this one.
+ * Applications should not update their UI to display browse
+ * results when the MoreComing flag is set, because this would
+ * result in a great deal of ugly flickering on the screen.
+ * Applications should instead wait until until MoreComing is not set,
+ * and then update their UI.
+ * When MoreComing is not set, that doesn't mean there will be no more
+ * answers EVER, just that there are no more answers immediately
+ * available right now at this instant. If more answers become available
+ * in the future they will be delivered as usual.
+ */
+
+ kDNSServiceFlagsAdd = 0x2,
+ kDNSServiceFlagsDefault = 0x4,
+ /* Flags for domain enumeration and browse/query reply callbacks.
+ * "Default" applies only to enumeration and is only valid in
+ * conjuction with "Add". An enumeration callback with the "Add"
+ * flag NOT set indicates a "Remove", i.e. the domain is no longer
+ * valid.
+ */
+
+ kDNSServiceFlagsNoAutoRename = 0x8,
+ /* Flag for specifying renaming behavior on name conflict when registering
+ * non-shared records. By default, name conflicts are automatically handled
+ * by renaming the service. NoAutoRename overrides this behavior - with this
+ * flag set, name conflicts will result in a callback. The NoAutorename flag
+ * is only valid if a name is explicitly specified when registering a service
+ * (i.e. the default name is not used.)
+ */
+
+ kDNSServiceFlagsShared = 0x10,
+ kDNSServiceFlagsUnique = 0x20,
+ /* Flag for registering individual records on a connected
+ * DNSServiceRef. Shared indicates that there may be multiple records
+ * with this name on the network (e.g. PTR records). Unique indicates that the
+ * record's name is to be unique on the network (e.g. SRV records).
+ */
+
+ kDNSServiceFlagsBrowseDomains = 0x40,
+ kDNSServiceFlagsRegistrationDomains = 0x80,
+ /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains.
+ * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains
+ * enumerates domains recommended for registration.
+ */
+
+ kDNSServiceFlagsLongLivedQuery = 0x100,
+ /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */
+
+ kDNSServiceFlagsAllowRemoteQuery = 0x200,
+ /* Flag for creating a record for which we will answer remote queries
+ * (queries from hosts more than one hop away; hosts not directly connected to the local link).
+ */
+
+ kDNSServiceFlagsForceMulticast = 0x400,
+ /* Flag for signifying that a query or registration should be performed exclusively via multicast DNS,
+ * even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS.
+ */
+
+ kDNSServiceFlagsReturnCNAME = 0x800
+ /* Flag for returning CNAME records in the DNSServiceQueryRecord call. CNAME records are
+ * normally followed without indicating to the client that there was a CNAME record.
+ */
+ };
+
+/*
+ * The values for DNS Classes and Types are listed in RFC 1035, and are available
+ * on every OS in its DNS header file. Unfortunately every OS does not have the
+ * same header file containing DNS Class and Type constants, and the names of
+ * the constants are not consistent. For example, BIND 8 uses "T_A",
+ * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc.
+ * For this reason, these constants are also listed here, so that code using
+ * the DNS-SD programming APIs can use these constants, so that the same code
+ * can compile on all our supported platforms.
+ */
+
+enum
+ {
+ kDNSServiceClass_IN = 1 /* Internet */
+ };
+
+enum
+ {
+ kDNSServiceType_A = 1, /* Host address. */
+ kDNSServiceType_NS = 2, /* Authoritative server. */
+ kDNSServiceType_MD = 3, /* Mail destination. */
+ kDNSServiceType_MF = 4, /* Mail forwarder. */
+ kDNSServiceType_CNAME = 5, /* Canonical name. */
+ kDNSServiceType_SOA = 6, /* Start of authority zone. */
+ kDNSServiceType_MB = 7, /* Mailbox domain name. */
+ kDNSServiceType_MG = 8, /* Mail group member. */
+ kDNSServiceType_MR = 9, /* Mail rename name. */
+ kDNSServiceType_NULL = 10, /* Null resource record. */
+ kDNSServiceType_WKS = 11, /* Well known service. */
+ kDNSServiceType_PTR = 12, /* Domain name pointer. */
+ kDNSServiceType_HINFO = 13, /* Host information. */
+ kDNSServiceType_MINFO = 14, /* Mailbox information. */
+ kDNSServiceType_MX = 15, /* Mail routing information. */
+ kDNSServiceType_TXT = 16, /* One or more text strings. */
+ kDNSServiceType_RP = 17, /* Responsible person. */
+ kDNSServiceType_AFSDB = 18, /* AFS cell database. */
+ kDNSServiceType_X25 = 19, /* X_25 calling address. */
+ kDNSServiceType_ISDN = 20, /* ISDN calling address. */
+ kDNSServiceType_RT = 21, /* Router. */
+ kDNSServiceType_NSAP = 22, /* NSAP address. */
+ kDNSServiceType_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */
+ kDNSServiceType_SIG = 24, /* Security signature. */
+ kDNSServiceType_KEY = 25, /* Security key. */
+ kDNSServiceType_PX = 26, /* X.400 mail mapping. */
+ kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */
+ kDNSServiceType_AAAA = 28, /* IPv6 Address. */
+ kDNSServiceType_LOC = 29, /* Location Information. */
+ kDNSServiceType_NXT = 30, /* Next domain (security). */
+ kDNSServiceType_EID = 31, /* Endpoint identifier. */
+ kDNSServiceType_NIMLOC = 32, /* Nimrod Locator. */
+ kDNSServiceType_SRV = 33, /* Server Selection. */
+ kDNSServiceType_ATMA = 34, /* ATM Address */
+ kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */
+ kDNSServiceType_KX = 36, /* Key Exchange */
+ kDNSServiceType_CERT = 37, /* Certification record */
+ kDNSServiceType_A6 = 38, /* IPv6 Address (deprecated) */
+ kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */
+ kDNSServiceType_SINK = 40, /* Kitchen sink (experimentatl) */
+ kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */
+ kDNSServiceType_TKEY = 249, /* Transaction key */
+ kDNSServiceType_TSIG = 250, /* Transaction signature. */
+ kDNSServiceType_IXFR = 251, /* Incremental zone transfer. */
+ kDNSServiceType_AXFR = 252, /* Transfer zone of authority. */
+ kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */
+ kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */
+ kDNSServiceType_ANY = 255 /* Wildcard match. */
+ };
+
+
+/* possible error code values */
+enum
+ {
+ kDNSServiceErr_NoError = 0,
+ kDNSServiceErr_Unknown = -65537, /* 0xFFFE FFFF */
+ kDNSServiceErr_NoSuchName = -65538,
+ kDNSServiceErr_NoMemory = -65539,
+ kDNSServiceErr_BadParam = -65540,
+ kDNSServiceErr_BadReference = -65541,
+ kDNSServiceErr_BadState = -65542,
+ kDNSServiceErr_BadFlags = -65543,
+ kDNSServiceErr_Unsupported = -65544,
+ kDNSServiceErr_NotInitialized = -65545,
+ kDNSServiceErr_AlreadyRegistered = -65547,
+ kDNSServiceErr_NameConflict = -65548,
+ kDNSServiceErr_Invalid = -65549,
+ kDNSServiceErr_Firewall = -65550,
+ kDNSServiceErr_Incompatible = -65551, /* client library incompatible with daemon */
+ kDNSServiceErr_BadInterfaceIndex = -65552,
+ kDNSServiceErr_Refused = -65553,
+ kDNSServiceErr_NoSuchRecord = -65554,
+ kDNSServiceErr_NoAuth = -65555,
+ kDNSServiceErr_NoSuchKey = -65556,
+ kDNSServiceErr_NATTraversal = -65557,
+ kDNSServiceErr_DoubleNAT = -65558,
+ kDNSServiceErr_BadTime = -65559
+ /* mDNS Error codes are in the range
+ * FFFE FF00 (-65792) to FFFE FFFF (-65537) */
+ };
+
+
+/* Maximum length, in bytes, of a service name represented as a */
+/* literal C-String, including the terminating NULL at the end. */
+
+#define kDNSServiceMaxServiceName 64
+
+/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
+/* including the final trailing dot, and the C-String terminating NULL at the end. */
+
+#define kDNSServiceMaxDomainName 1005
+
+/*
+ * Notes on DNS Name Escaping
+ * -- or --
+ * "Why is kDNSServiceMaxDomainName 1005, when the maximum legal domain name is 255 bytes?"
+ *
+ * All strings used in DNS-SD are UTF-8 strings.
+ * With few exceptions, most are also escaped using standard DNS escaping rules:
+ *
+ * '\\' represents a single literal '\' in the name
+ * '\.' represents a single literal '.' in the name
+ * '\ddd', where ddd is a three-digit decimal value from 000 to 255,
+ * represents a single literal byte with that value.
+ * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain.
+ *
+ * The exceptions, that do not use escaping, are the routines where the full
+ * DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
+ * In these routines, the "servicename" is NOT escaped. It does not need to be, since
+ * it is, by definition, just a single literal string. Any characters in that string
+ * represent exactly what they are. The "regtype" portion is, technically speaking,
+ * escaped, but since legal regtypes are only allowed to contain letters, digits,
+ * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
+ * portion is also escaped, though most domains in use on the public Internet
+ * today, like regtypes, don't contain any characters that need to be escaped.
+ * As DNS-SD becomes more popular, rich-text domains for service discovery will
+ * become common, so software should be written to cope with domains with escaping.
+ *
+ * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
+ * terminating NULL at the end). The regtype is of the form _service._tcp or
+ * _service._udp, where the "service" part is 1-14 characters, which may be
+ * letters, digits, or hyphens. The domain part of the three-part name may be
+ * any legal domain, providing that the resulting servicename+regtype+domain
+ * name does not exceed 255 bytes.
+ *
+ * For most software, these issues are transparent. When browsing, the discovered
+ * servicenames should simply be displayed as-is. When resolving, the discovered
+ * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve().
+ * When a DNSServiceResolve() succeeds, the returned fullname is already in
+ * the correct format to pass to standard system DNS APIs such as res_query().
+ * For converting from servicename/regtype/domain to a single properly-escaped
+ * full DNS name, the helper function DNSServiceConstructFullName() is provided.
+ *
+ * The following (highly contrived) example illustrates the escaping process.
+ * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
+ * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
+ * The full (escaped) DNS name of this service's SRV record would be:
+ * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
+ */
+
+
+/*
+ * Constants for specifying an interface index
+ *
+ * Specific interface indexes are identified via a 32-bit unsigned integer returned
+ * by the if_nametoindex() family of calls.
+ *
+ * If the client passes 0 for interface index, that means "do the right thing",
+ * which (at present) means, "if the name is in an mDNS local multicast domain
+ * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
+ * on all applicable interfaces, otherwise send via unicast to the appropriate
+ * DNS server." Normally, most clients will use 0 for interface index to
+ * automatically get the default sensible behaviour.
+ *
+ * If the client passes a positive interface index, then for multicast names that
+ * indicates to do the operation only on that one interface. For unicast names the
+ * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
+ *
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
+ * a service, then that service will be found *only* by other local clients
+ * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
+ * or kDNSServiceInterfaceIndexAny.
+ * If a client has a 'private' service, accessible only to other processes
+ * running on the same machine, this allows the client to advertise that service
+ * in a way such that it does not inadvertently appear in service lists on
+ * all the other machines on the network.
+ *
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
+ * then it will find *all* records registered on that same local machine.
+ * Clients explicitly wishing to discover *only* LocalOnly services can
+ * accomplish this by inspecting the interfaceIndex of each service reported
+ * to their DNSServiceBrowseReply() callback function, and discarding those
+ * where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
+ */
+
+#define kDNSServiceInterfaceIndexAny 0
+#define kDNSServiceInterfaceIndexLocalOnly ( (uint32_t) -1 )
+
+
+typedef uint32_t DNSServiceFlags;
+typedef int32_t DNSServiceErrorType;
+
+
+/*********************************************************************************************
+ *
+ * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
+ *
+ *********************************************************************************************/
+
+
+/* DNSServiceRefSockFD()
+ *
+ * Access underlying Unix domain socket for an initialized DNSServiceRef.
+ * The DNS Service Discovery implmementation uses this socket to communicate between
+ * the client and the mDNSResponder daemon. The application MUST NOT directly read from
+ * or write to this socket. Access to the socket is provided so that it can be used as a
+ * run loop source, or in a select() loop: when data is available for reading on the socket,
+ * DNSServiceProcessResult() should be called, which will extract the daemon's reply from
+ * the socket, and pass it to the appropriate application callback. By using a run loop or
+ * select(), results from the daemon can be processed asynchronously. Without using these
+ * constructs, DNSServiceProcessResult() will block until the response from the daemon arrives.
+ * The client is responsible for ensuring that the data on the socket is processed in a timely
+ * fashion - the daemon may terminate its connection with a client that does not clear its
+ * socket buffer.
+ *
+ * sdRef: A DNSServiceRef initialized by any of the DNSService calls.
+ *
+ * return value: The DNSServiceRef's underlying socket descriptor, or -1 on
+ * error.
+ */
+
+int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
+
+
+/* DNSServiceProcessResult()
+ *
+ * Read a reply from the daemon, calling the appropriate application callback. This call will
+ * block until the daemon's response is received. Use DNSServiceRefSockFD() in
+ * conjunction with a run loop or select() to determine the presence of a response from the
+ * server before calling this function to process the reply without blocking. Call this function
+ * at any point if it is acceptable to block until the daemon's response arrives. Note that the
+ * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is
+ * a reply from the daemon - the daemon may terminate its connection with a client that does not
+ * process the daemon's responses.
+ *
+ * sdRef: A DNSServiceRef initialized by any of the DNSService calls
+ * that take a callback parameter.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
+ * an error code indicating the specific failure that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef);
+
+
+/* DNSServiceRefDeallocate()
+ *
+ * Terminate a connection with the daemon and free memory associated with the DNSServiceRef.
+ * Any services or records registered with this DNSServiceRef will be deregistered. Any
+ * Browse, Resolve, or Query operations called with this reference will be terminated.
+ *
+ * Note: If the reference's underlying socket is used in a run loop or select() call, it should
+ * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's
+ * socket.
+ *
+ * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs
+ * created via this reference will be invalidated by this call - the resource records are
+ * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly,
+ * if the reference was initialized with DNSServiceRegister, and an extra resource record was
+ * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call
+ * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent
+ * functions.
+ *
+ * Note: This call is to be used only with the DNSServiceRef defined by this API. It is
+ * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based
+ * DNSServiceDiscovery.h API.
+ *
+ * sdRef: A DNSServiceRef initialized by any of the DNSService calls.
+ *
+ */
+
+void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef);
+
+
+/*********************************************************************************************
+ *
+ * Domain Enumeration
+ *
+ *********************************************************************************************/
+
+/* DNSServiceEnumerateDomains()
+ *
+ * Asynchronously enumerate domains available for browsing and registration.
+ *
+ * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
+ * are to be found.
+ *
+ * Note that the names returned are (like all of DNS-SD) UTF-8 strings,
+ * and are escaped using standard DNS escaping rules.
+ * (See "Notes on DNS Name Escaping" earlier in this file for more details.)
+ * A graphical browser displaying a hierarchical tree-structured view should cut
+ * the names at the bare dots to yield individual labels, then de-escape each
+ * label according to the escaping rules, and then display the resulting UTF-8 text.
+ *
+ * DNSServiceDomainEnumReply Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceEnumerateDomains().
+ *
+ * flags: Possible values are:
+ * kDNSServiceFlagsMoreComing
+ * kDNSServiceFlagsAdd
+ * kDNSServiceFlagsDefault
+ *
+ * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given
+ * interface is determined via the if_nametoindex() family of calls.)
+ *
+ * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
+ * the failure that occurred (other parameters are undefined if errorCode is nonzero).
+ *
+ * replyDomain: The name of the domain.
+ *
+ * context: The context pointer passed to DNSServiceEnumerateDomains.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceDomainEnumReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *replyDomain,
+ void *context
+ );
+
+
+/* DNSServiceEnumerateDomains() Parameters:
+ *
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the enumeration operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Possible values are:
+ * kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing.
+ * kDNSServiceFlagsRegistrationDomains to enumerate domains recommended
+ * for registration.
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to look for domains.
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Most applications will pass 0 to enumerate domains on
+ * all interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * callBack: The function to be called when a domain is found or the call asynchronously
+ * fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is not invoked and the DNSServiceRef
+ * is not initialized.)
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceDomainEnumReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * Service Registration
+ *
+ *********************************************************************************************/
+
+/* Register a service that is discovered via Browse() and Resolve() calls.
+ *
+ *
+ * DNSServiceRegisterReply() Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceRegister().
+ *
+ * flags: Currently unused, reserved for future use.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred (including name conflicts,
+ * if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
+ * Other parameters are undefined if errorCode is nonzero.
+ *
+ * name: The service name registered (if the application did not specify a name in
+ * DNSServiceRegister(), this indicates what name was automatically chosen).
+ *
+ * regtype: The type of service registered, as it was passed to the callout.
+ *
+ * domain: The domain on which the service was registered (if the application did not
+ * specify a domain in DNSServiceRegister(), this indicates the default domain
+ * on which the service was registered).
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceRegisterReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorCode,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ void *context
+ );
+
+
+/* DNSServiceRegister() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the registration will remain active indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to register the service
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Most applications will pass 0 to register on all
+ * available interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * flags: Indicates the renaming behavior on name conflict (most applications
+ * will pass 0). See flag definitions above for details.
+ *
+ * name: If non-NULL, specifies the service name to be registered.
+ * Most applications will not specify a name, in which case the computer
+ * name is used (this name is communicated to the client via the callback).
+ * If a name is specified, it must be 1-63 bytes of UTF-8 text.
+ * If the name is longer than 63 bytes it will be automatically truncated
+ * to a legal length, unless the NoAutoRename flag is set,
+ * in which case kDNSServiceErr_BadParam will be returned.
+ *
+ * regtype: The service type followed by the protocol, separated by a dot
+ * (e.g. "_ftp._tcp"). The service type must be an underscore, followed
+ * by 1-14 characters, which may be letters, digits, or hyphens.
+ * The transport protocol must be "_tcp" or "_udp". New service types
+ * should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
+ *
+ * domain: If non-NULL, specifies the domain on which to advertise the service.
+ * Most applications will not specify a domain, instead automatically
+ * registering in the default domain(s).
+ *
+ * host: If non-NULL, specifies the SRV target host name. Most applications
+ * will not specify a host, instead automatically using the machine's
+ * default host name(s). Note that specifying a non-NULL host does NOT
+ * create an address record for that host - the application is responsible
+ * for ensuring that the appropriate address record exists, or creating it
+ * via DNSServiceRegisterRecord().
+ *
+ * port: The port, in network byte order, on which the service accepts connections.
+ * Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
+ * by browsing, but will cause a name conflict if another client tries to
+ * register that same name). Most clients will not use placeholder services.
+ *
+ * txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
+ *
+ * txtRecord: The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
+ * TXT record, i.e. <length byte> <data> <length byte> <data> ...
+ * Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
+ * i.e. it creates a TXT record of length one containing a single empty string.
+ * RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
+ * string is the smallest legal DNS TXT record.
+ * As with the other parameters, the DNSServiceRegister call copies the txtRecord
+ * data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
+ * then you can safely free that memory right after the DNSServiceRegister call returns.
+ *
+ * callBack: The function to be called when the registration completes or asynchronously
+ * fails. The client MAY pass NULL for the callback - The client will NOT be notified
+ * of the default values picked on its behalf, and the client will NOT be notified of any
+ * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
+ * of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
+ * The client may still deregister the service at any time via DNSServiceRefDeallocate().
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSServiceRef
+ * is not initialized.)
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRegister
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name, /* may be NULL */
+ const char *regtype,
+ const char *domain, /* may be NULL */
+ const char *host, /* may be NULL */
+ uint16_t port,
+ uint16_t txtLen,
+ const void *txtRecord, /* may be NULL */
+ DNSServiceRegisterReply callBack, /* may be NULL */
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceAddRecord()
+ *
+ * Add a record to a registered service. The name of the record will be the same as the
+ * registered service's name.
+ * The record can later be updated or deregistered by passing the RecordRef initialized
+ * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ *
+ * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
+ * with respect to a single DNSServiceRef. If you plan to have multiple threads
+ * in your program simultaneously add, update, or remove records from the same
+ * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
+ * or take similar appropriate precautions to serialize those calls.
+ *
+ *
+ * Parameters;
+ *
+ * sdRef: A DNSServiceRef initialized by DNSServiceRegister().
+ *
+ * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
+ * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ * If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also
+ * invalidated and may not be used further.
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * rrtype: The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc)
+ *
+ * rdlen: The length, in bytes, of the rdata.
+ *
+ * rdata: The raw rdata to be contained in the added resource record.
+ *
+ * ttl: The time to live of the resource record, in seconds. Pass 0 to use a default value.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an
+ * error code indicating the error that occurred (the RecordRef is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceAddRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ DNSServiceFlags flags,
+ uint16_t rrtype,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl
+ );
+
+
+/* DNSServiceUpdateRecord
+ *
+ * Update a registered resource record. The record must either be:
+ * - The primary txt record of a service registered via DNSServiceRegister()
+ * - A record added to a registered service via DNSServiceAddRecord()
+ * - An individual record registered by DNSServiceRegisterRecord()
+ *
+ *
+ * Parameters:
+ *
+ * sdRef: A DNSServiceRef that was initialized by DNSServiceRegister()
+ * or DNSServiceCreateConnection().
+ *
+ * RecordRef: A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
+ * service's primary txt record.
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * rdlen: The length, in bytes, of the new rdata.
+ *
+ * rdata: The new rdata to be contained in the updated resource record.
+ *
+ * ttl: The time to live of the updated resource record, in seconds.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an
+ * error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef, /* may be NULL */
+ DNSServiceFlags flags,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl
+ );
+
+
+/* DNSServiceRemoveRecord
+ *
+ * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
+ * an record registered individually via DNSServiceRegisterRecord().
+ *
+ * Parameters:
+ *
+ * sdRef: A DNSServiceRef initialized by DNSServiceRegister() (if the
+ * record being removed was registered via DNSServiceAddRecord()) or by
+ * DNSServiceCreateConnection() (if the record being removed was registered via
+ * DNSServiceRegisterRecord()).
+ *
+ * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord()
+ * or DNSServiceRegisterRecord().
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an
+ * error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
+ DNSServiceFlags flags
+ );
+
+
+/*********************************************************************************************
+ *
+ * Service Discovery
+ *
+ *********************************************************************************************/
+
+/* Browse for instances of a service.
+ *
+ *
+ * DNSServiceBrowseReply() Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceBrowse().
+ *
+ * flags: Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
+ * See flag definitions for details.
+ *
+ * interfaceIndex: The interface on which the service is advertised. This index should
+ * be passed to DNSServiceResolve() when resolving the service.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will
+ * indicate the failure that occurred. Other parameters are undefined if
+ * the errorCode is nonzero.
+ *
+ * serviceName: The discovered service name. This name should be displayed to the user,
+ * and stored for subsequent use in the DNSServiceResolve() call.
+ *
+ * regtype: The service type, which is usually (but not always) the same as was passed
+ * to DNSServiceBrowse(). One case where the discovered service type may
+ * not be the same as the requested service type is when using subtypes:
+ * The client may want to browse for only those ftp servers that allow
+ * anonymous connections. The client will pass the string "_ftp._tcp,_anon"
+ * to DNSServiceBrowse(), but the type of the service that's discovered
+ * is simply "_ftp._tcp". The regtype for each discovered service instance
+ * should be stored along with the name, so that it can be passed to
+ * DNSServiceResolve() when the service is later resolved.
+ *
+ * domain: The domain of the discovered service instance. This may or may not be the
+ * same as the domain that was passed to DNSServiceBrowse(). The domain for each
+ * discovered service instance should be stored along with the name, so that
+ * it can be passed to DNSServiceResolve() when the service is later resolved.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceBrowseReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *serviceName,
+ const char *regtype,
+ const char *replyDomain,
+ void *context
+ );
+
+
+/* DNSServiceBrowse() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the browse operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to browse for services
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Most applications will pass 0 to browse on all available
+ * interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * regtype: The service type being browsed for followed by the protocol, separated by a
+ * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ *
+ * domain: If non-NULL, specifies the domain on which to browse for services.
+ * Most applications will not specify a domain, instead browsing on the
+ * default domain(s).
+ *
+ * callBack: The function to be called when an instance of the service being browsed for
+ * is found, or if the call asynchronously fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is not invoked and the DNSServiceRef
+ * is not initialized.)
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceBrowse
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *regtype,
+ const char *domain, /* may be NULL */
+ DNSServiceBrowseReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceResolve()
+ *
+ * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
+ * txt record.
+ *
+ * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
+ * DNSServiceQueryRecord() instead, as it is more efficient for this task.
+ *
+ * Note: When the desired results have been returned, the client MUST terminate the resolve by calling
+ * DNSServiceRefDeallocate().
+ *
+ * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
+ * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
+ * DNSServiceQueryRecord() should be used.
+ *
+ * DNSServiceResolveReply Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceResolve().
+ *
+ * flags: Currently unused, reserved for future use.
+ *
+ * interfaceIndex: The interface on which the service was resolved.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will
+ * indicate the failure that occurred. Other parameters are undefined if
+ * the errorCode is nonzero.
+ *
+ * fullname: The full service domain name, in the form <servicename>.<protocol>.<domain>.
+ * (This name is escaped following standard DNS rules, making it suitable for
+ * passing to standard system DNS APIs such as res_query(), or to the
+ * special-purpose functions included in this API that take fullname parameters.
+ * See "Notes on DNS Name Escaping" earlier in this file for more details.)
+ *
+ * hosttarget: The target hostname of the machine providing the service. This name can
+ * be passed to functions like gethostbyname() to identify the host's IP address.
+ *
+ * port: The port, in network byte order, on which connections are accepted for this service.
+ *
+ * txtLen: The length of the txt record, in bytes.
+ *
+ * txtRecord: The service's primary txt record, in standard txt record format.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
+ * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
+ * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
+ * These should be fixed by updating your own callback function definition to match the corrected
+ * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
+ * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
+ * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
+ * If you need to maintain portable code that will compile cleanly with both the old and new versions of
+ * this header file, you should update your callback function definition to use the correct unsigned value,
+ * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
+ * the compiler warning, e.g.:
+ * DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
+ * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
+ * with both the old header and with the new corrected version.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceResolveReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t port,
+ uint16_t txtLen,
+ const unsigned char *txtRecord,
+ void *context
+ );
+
+
+/* DNSServiceResolve() Parameters
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the resolve operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * interfaceIndex: The interface on which to resolve the service. If this resolve call is
+ * as a result of a currently active DNSServiceBrowse() operation, then the
+ * interfaceIndex should be the index reported in the DNSServiceBrowseReply
+ * callback. If this resolve call is using information previously saved
+ * (e.g. in a preference file) for later use, then use interfaceIndex 0, because
+ * the desired service may now be reachable via a different physical interface.
+ * See "Constants for specifying an interface index" for more details.
+ *
+ * name: The name of the service instance to be resolved, as reported to the
+ * DNSServiceBrowseReply() callback.
+ *
+ * regtype: The type of the service instance to be resolved, as reported to the
+ * DNSServiceBrowseReply() callback.
+ *
+ * domain: The domain of the service instance to be resolved, as reported to the
+ * DNSServiceBrowseReply() callback.
+ *
+ * callBack: The function to be called when a result is found, or if the call
+ * asynchronously fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSServiceRef
+ * is not initialized.)
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceResolve
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ DNSServiceResolveReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * Special Purpose Calls (most applications will not use these)
+ *
+ *********************************************************************************************/
+
+/* DNSServiceCreateConnection()
+ *
+ * Create a connection to the daemon allowing efficient registration of
+ * multiple individual records.
+ *
+ *
+ * Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating
+ * the reference (via DNSServiceRefDeallocate()) severs the
+ * connection and deregisters all records registered on this connection.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
+ * an error code indicating the specific failure that occurred (in which
+ * case the DNSServiceRef is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
+
+
+/* DNSServiceRegisterRecord
+ *
+ * Register an individual resource record on a connected DNSServiceRef.
+ *
+ * Note that name conflicts occurring for records registered via this call must be handled
+ * by the client in the callback.
+ *
+ *
+ * DNSServiceRegisterRecordReply() parameters:
+ *
+ * sdRef: The connected DNSServiceRef initialized by
+ * DNSServiceCreateConnection().
+ *
+ * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above
+ * DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is
+ * invalidated, and may not be used further.
+ *
+ * flags: Currently unused, reserved for future use.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred (including name conflicts.)
+ * Other parameters are undefined if errorCode is nonzero.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+ typedef void (DNSSD_API *DNSServiceRegisterRecordReply)
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorCode,
+ void *context
+ );
+
+
+/* DNSServiceRegisterRecord() Parameters:
+ *
+ * sdRef: A DNSServiceRef initialized by DNSServiceCreateConnection().
+ *
+ * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
+ * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ * (To deregister ALL records registered on a single connected DNSServiceRef
+ * and deallocate each of their corresponding DNSServiceRecordRefs, call
+ * DNSServiceRefDealloocate()).
+ *
+ * flags: Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique
+ * (see flag type definitions for details).
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to register the record
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Passing 0 causes the record to be registered on all interfaces.
+ * See "Constants for specifying an interface index" for more details.
+ *
+ * fullname: The full domain name of the resource record.
+ *
+ * rrtype: The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN)
+ *
+ * rdlen: Length, in bytes, of the rdata.
+ *
+ * rdata: A pointer to the raw rdata, as it is to appear in the DNS record.
+ *
+ * ttl: The time to live of the resource record, in seconds. Pass 0 to use a default value.
+ *
+ * callBack: The function to be called when a result is found, or if the call
+ * asynchronously fails (e.g. because of a name conflict.)
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSRecordRef is
+ * not initialized.)
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ DNSServiceRegisterRecordReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceQueryRecord
+ *
+ * Query for an arbitrary DNS record.
+ *
+ *
+ * DNSServiceQueryRecordReply() Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceQueryRecord().
+ *
+ * flags: Possible values are kDNSServiceFlagsMoreComing and
+ * kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records
+ * with a ttl of 0, i.e. "Remove" events.
+ *
+ * interfaceIndex: The interface on which the query was resolved (the index for a given
+ * interface is determined via the if_nametoindex() family of calls).
+ * See "Constants for specifying an interface index" for more details.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred. Other parameters are undefined if
+ * errorCode is nonzero.
+ *
+ * fullname: The resource record's full domain name.
+ *
+ * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * rdlen: The length, in bytes, of the resource record rdata.
+ *
+ * rdata: The raw rdata of the resource record.
+ *
+ * ttl: The resource record's time to live, in seconds.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceQueryRecordReply)
+ (
+ DNSServiceRef DNSServiceRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+ );
+
+
+/* DNSServiceQueryRecord() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the query operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
+ * query in a non-local domain. Without setting this flag, unicast queries
+ * will be one-shot - that is, only answers available at the time of the call
+ * will be returned. By setting this flag, answers (including Add and Remove
+ * events) that become available after the initial call is made will generate
+ * callbacks. This flag has no effect on link-local multicast queries.
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to issue the query
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Passing 0 causes the name to be queried for on all
+ * interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * fullname: The full domain name of the resource record to be queried for.
+ *
+ * rrtype: The numerical type of the resource record to be queried for
+ * (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * callBack: The function to be called when a result is found, or if the call
+ * asynchronously fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSServiceRef
+ * is not initialized.)
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ DNSServiceQueryRecordReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceReconfirmRecord
+ *
+ * Instruct the daemon to verify the validity of a resource record that appears to
+ * be out of date (e.g. because tcp connection to a service's target failed.)
+ * Causes the record to be flushed from the daemon's cache (as well as all other
+ * daemons' caches on the network) if the record is determined to be invalid.
+ *
+ * Parameters:
+ *
+ * flags: Currently unused, reserved for future use.
+ *
+ * interfaceIndex: If non-zero, specifies the interface of the record in question.
+ * Passing 0 causes all instances of this record to be reconfirmed.
+ *
+ * fullname: The resource record's full domain name.
+ *
+ * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * rdlen: The length, in bytes, of the resource record rdata.
+ *
+ * rdata: The raw rdata of the resource record.
+ *
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
+ (
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata
+ );
+
+
+/*********************************************************************************************
+ *
+ * General Utility Functions
+ *
+ *********************************************************************************************/
+
+/* DNSServiceConstructFullName()
+ *
+ * Concatenate a three-part domain name (as returned by the above callbacks) into a
+ * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
+ * strings where necessary.
+ *
+ * Parameters:
+ *
+ * fullName: A pointer to a buffer that where the resulting full domain name is to be written.
+ * The buffer must be kDNSServiceMaxDomainName (1005) bytes in length to
+ * accommodate the longest legal domain name without buffer overrun.
+ *
+ * service: The service name - any dots or backslashes must NOT be escaped.
+ * May be NULL (to construct a PTR record name, e.g.
+ * "_ftp._tcp.apple.com.").
+ *
+ * regtype: The service type followed by the protocol, separated by a dot
+ * (e.g. "_ftp._tcp").
+ *
+ * domain: The domain name, e.g. "apple.com.". Literal dots or backslashes,
+ * if any, must be escaped, e.g. "1st\. Floor.apple.com."
+ *
+ * return value: Returns 0 on success, -1 on error.
+ *
+ */
+
+int DNSSD_API DNSServiceConstructFullName
+ (
+ char *fullName,
+ const char *service, /* may be NULL */
+ const char *regtype,
+ const char *domain
+ );
+
+
+/*********************************************************************************************
+ *
+ * TXT Record Construction Functions
+ *
+ *********************************************************************************************/
+
+/*
+ * A typical calling sequence for TXT record construction is something like:
+ *
+ * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack)
+ * TXTRecordCreate();
+ * TXTRecordSetValue();
+ * TXTRecordSetValue();
+ * TXTRecordSetValue();
+ * ...
+ * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... );
+ * TXTRecordDeallocate();
+ * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack)
+ */
+
+
+/* TXTRecordRef
+ *
+ * Opaque internal data type.
+ * Note: Represents a DNS-SD TXT record.
+ */
+
+typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
+
+
+/* TXTRecordCreate()
+ *
+ * Creates a new empty TXTRecordRef referencing the specified storage.
+ *
+ * If the buffer parameter is NULL, or the specified storage size is not
+ * large enough to hold a key subsequently added using TXTRecordSetValue(),
+ * then additional memory will be added as needed using malloc().
+ *
+ * On some platforms, when memory is low, malloc() may fail. In this
+ * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this
+ * error condition will need to be handled as appropriate by the caller.
+ *
+ * You can avoid the need to handle this error condition if you ensure
+ * that the storage you initially provide is large enough to hold all
+ * the key/value pairs that are to be added to the record.
+ * The caller can precompute the exact length required for all of the
+ * key/value pairs to be added, or simply provide a fixed-sized buffer
+ * known in advance to be large enough.
+ * A no-value (key-only) key requires (1 + key length) bytes.
+ * A key with empty value requires (1 + key length + 1) bytes.
+ * A key with non-empty value requires (1 + key length + 1 + value length).
+ * For most applications, DNS-SD TXT records are generally
+ * less than 100 bytes, so in most cases a simple fixed-sized
+ * 256-byte buffer will be more than sufficient.
+ * Recommended size limits for DNS-SD TXT Records are discussed in
+ * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ *
+ * Note: When passing parameters to and from these TXT record APIs,
+ * the key name does not include the '=' character. The '=' character
+ * is the separator between the key and value in the on-the-wire
+ * packet format; it is not part of either the key or the value.
+ *
+ * txtRecord: A pointer to an uninitialized TXTRecordRef.
+ *
+ * bufferLen: The size of the storage provided in the "buffer" parameter.
+ *
+ * buffer: Optional caller-supplied storage used to hold the TXTRecord data.
+ * This storage must remain valid for as long as
+ * the TXTRecordRef.
+ */
+
+void DNSSD_API TXTRecordCreate
+ (
+ TXTRecordRef *txtRecord,
+ uint16_t bufferLen,
+ void *buffer
+ );
+
+
+/* TXTRecordDeallocate()
+ *
+ * Releases any resources allocated in the course of preparing a TXT Record
+ * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue().
+ * Ownership of the buffer provided in TXTRecordCreate() returns to the client.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ */
+
+void DNSSD_API TXTRecordDeallocate
+ (
+ TXTRecordRef *txtRecord
+ );
+
+
+/* TXTRecordSetValue()
+ *
+ * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already
+ * exists in the TXTRecordRef, then the current value will be replaced with
+ * the new value.
+ * Keys may exist in four states with respect to a given TXT record:
+ * - Absent (key does not appear at all)
+ * - Present with no value ("key" appears alone)
+ * - Present with empty value ("key=" appears in TXT record)
+ * - Present with non-empty value ("key=value" appears in TXT record)
+ * For more details refer to "Data Syntax for DNS-SD TXT Records" in
+ * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * key: A null-terminated string which only contains printable ASCII
+ * values (0x20-0x7E), excluding '=' (0x3D). Keys should be
+ * 8 characters or less (not counting the terminating null).
+ *
+ * valueSize: The size of the value.
+ *
+ * value: Any binary value. For values that represent
+ * textual data, UTF-8 is STRONGLY recommended.
+ * For values that represent textual data, valueSize
+ * should NOT include the terminating null (if any)
+ * at the end of the string.
+ * If NULL, then "key" will be added with no value.
+ * If non-NULL but valueSize is zero, then "key=" will be
+ * added with empty value.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success.
+ * Returns kDNSServiceErr_Invalid if the "key" string contains
+ * illegal characters.
+ * Returns kDNSServiceErr_NoMemory if adding this key would
+ * exceed the available storage.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordSetValue
+ (
+ TXTRecordRef *txtRecord,
+ const char *key,
+ uint8_t valueSize, /* may be zero */
+ const void *value /* may be NULL */
+ );
+
+
+/* TXTRecordRemoveValue()
+ *
+ * Removes a key from a TXTRecordRef. The "key" must be an
+ * ASCII string which exists in the TXTRecordRef.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * key: A key name which exists in the TXTRecordRef.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success.
+ * Returns kDNSServiceErr_NoSuchKey if the "key" does not
+ * exist in the TXTRecordRef.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
+ (
+ TXTRecordRef *txtRecord,
+ const char *key
+ );
+
+
+/* TXTRecordGetLength()
+ *
+ * Allows you to determine the length of the raw bytes within a TXTRecordRef.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * return value: Returns the size of the raw bytes inside a TXTRecordRef
+ * which you can pass directly to DNSServiceRegister() or
+ * to DNSServiceUpdateRecord().
+ * Returns 0 if the TXTRecordRef is empty.
+ */
+
+uint16_t DNSSD_API TXTRecordGetLength
+ (
+ const TXTRecordRef *txtRecord
+ );
+
+
+/* TXTRecordGetBytesPtr()
+ *
+ * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * return value: Returns a pointer to the raw bytes inside the TXTRecordRef
+ * which you can pass directly to DNSServiceRegister() or
+ * to DNSServiceUpdateRecord().
+ */
+
+const void * DNSSD_API TXTRecordGetBytesPtr
+ (
+ const TXTRecordRef *txtRecord
+ );
+
+
+/*********************************************************************************************
+ *
+ * TXT Record Parsing Functions
+ *
+ *********************************************************************************************/
+
+/*
+ * A typical calling sequence for TXT record parsing is something like:
+ *
+ * Receive TXT record data in DNSServiceResolve() callback
+ * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
+ * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
+ * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
+ * ...
+ * bcopy(val1ptr, myval1, len1);
+ * bcopy(val2ptr, myval2, len2);
+ * ...
+ * return;
+ *
+ * If you wish to retain the values after return from the DNSServiceResolve()
+ * callback, then you need to copy the data to your own storage using bcopy()
+ * or similar, as shown in the example above.
+ *
+ * If for some reason you need to parse a TXT record you built yourself
+ * using the TXT record construction functions above, then you can do
+ * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls:
+ * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len);
+ *
+ * Most applications only fetch keys they know about from a TXT record and
+ * ignore the rest.
+ * However, some debugging tools wish to fetch and display all keys.
+ * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls.
+ */
+
+/* TXTRecordContainsKey()
+ *
+ * Allows you to determine if a given TXT Record contains a specified key.
+ *
+ * txtLen: The size of the received TXT Record.
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * key: A null-terminated ASCII string containing the key name.
+ *
+ * return value: Returns 1 if the TXT Record contains the specified key.
+ * Otherwise, it returns 0.
+ */
+
+int DNSSD_API TXTRecordContainsKey
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key
+ );
+
+
+/* TXTRecordGetValuePtr()
+ *
+ * Allows you to retrieve the value for a given key from a TXT Record.
+ *
+ * txtLen: The size of the received TXT Record
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * key: A null-terminated ASCII string containing the key name.
+ *
+ * valueLen: On output, will be set to the size of the "value" data.
+ *
+ * return value: Returns NULL if the key does not exist in this TXT record,
+ * or exists with no value (to differentiate between
+ * these two cases use TXTRecordContainsKey()).
+ * Returns pointer to location within TXT Record bytes
+ * if the key exists with empty or non-empty value.
+ * For empty value, valueLen will be zero.
+ * For non-empty value, valueLen will be length of value data.
+ */
+
+const void * DNSSD_API TXTRecordGetValuePtr
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ uint8_t *valueLen
+ );
+
+
+/* TXTRecordGetCount()
+ *
+ * Returns the number of keys stored in the TXT Record. The count
+ * can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
+ *
+ * txtLen: The size of the received TXT Record.
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * return value: Returns the total number of keys in the TXT Record.
+ *
+ */
+
+uint16_t DNSSD_API TXTRecordGetCount
+ (
+ uint16_t txtLen,
+ const void *txtRecord
+ );
+
+
+/* TXTRecordGetItemAtIndex()
+ *
+ * Allows you to retrieve a key name and value pointer, given an index into
+ * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1.
+ * It's also possible to iterate through keys in a TXT record by simply
+ * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
+ * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
+ *
+ * On return:
+ * For keys with no value, *value is set to NULL and *valueLen is zero.
+ * For keys with empty value, *value is non-NULL and *valueLen is zero.
+ * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
+ *
+ * txtLen: The size of the received TXT Record.
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * index: An index into the TXT Record.
+ *
+ * keyBufLen: The size of the string buffer being supplied.
+ *
+ * key: A string buffer used to store the key name.
+ * On return, the buffer contains a null-terminated C string
+ * giving the key name. DNS-SD TXT keys are usually
+ * 8 characters or less. To hold the maximum possible
+ * key name, the buffer should be 256 bytes long.
+ *
+ * valueLen: On output, will be set to the size of the "value" data.
+ *
+ * value: On output, *value is set to point to location within TXT
+ * Record bytes that holds the value data.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success.
+ * Returns kDNSServiceErr_NoMemory if keyBufLen is too short.
+ * Returns kDNSServiceErr_Invalid if index is greater than
+ * TXTRecordGetCount()-1.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ uint16_t index,
+ uint16_t keyBufLen,
+ char *key,
+ uint8_t *valueLen,
+ const void **value
+ );
+
+#ifdef __APPLE_API_PRIVATE
+
+/*
+ * Mac OS X specific functionality
+ * 3rd party clients of this API should not depend on future support or availability of this routine
+ */
+
+/* DNSServiceSetDefaultDomainForUser()
+ *
+ * Set the default domain for the caller's UID. Future browse and registration
+ * calls by this user that do not specify an explicit domain will browse and
+ * register in this wide-area domain in addition to .local. In addition, this
+ * domain will be returned as a Browse domain via domain enumeration calls.
+ *
+ *
+ * Parameters:
+ *
+ * flags: Pass kDNSServiceFlagsAdd to add a domain for a user. Call without
+ * this flag set to clear a previously added domain.
+ *
+ * domain: The domain to be used for the caller's UID.
+ *
+ * return value: Returns kDNSServiceErr_NoError on succeses, otherwise returns
+ * an error code indicating the error that occurred
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
+ (
+ DNSServiceFlags flags,
+ const char *domain
+ );
+
+#endif //__APPLE_API_PRIVATE
+
+// Some C compiler cleverness. We can make the compiler check certain things for us,
+// and report errors at compile-time if anything is wrong. The usual way to do this would
+// be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
+// then you don't find out what's wrong until you run the software. This way, if the assertion
+// condition is false, the array size is negative, and the complier complains immediately.
+
+struct DNS_SD_CompileTimeAssertionChecks
+ {
+ char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
+ };
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _DNS_SD_H */
diff --git a/usr/src/lib/libdns_sd/common/dnssd_clientlib.c b/usr/src/lib/libdns_sd/common/dnssd_clientlib.c
new file mode 100644
index 0000000000..b5a45c8b63
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/dnssd_clientlib.c
@@ -0,0 +1,373 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+
+$Log: dnssd_clientlib.c,v $
+Revision 1.11 2006/08/14 23:05:53 cheshire
+Added "tab-width" emacs header line
+
+Revision 1.10 2005/04/06 02:06:56 shersche
+Add DNSSD_API macro to TXTRecord API calls
+
+Revision 1.9 2004/10/06 02:22:19 cheshire
+Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
+
+Revision 1.8 2004/10/01 22:15:55 rpantos
+rdar://problem/3824265: Replace APSL in client lib with BSD license.
+
+Revision 1.7 2004/06/26 03:16:34 shersche
+clean up warning messages on Win32 platform
+
+Submitted by: herscher
+
+Revision 1.6 2004/06/12 01:09:45 cheshire
+To be callable from the broadest range of clients on Windows (e.g. Visual Basic, C#, etc.)
+API routines have to be declared as "__stdcall", instead of the C default, "__cdecl"
+
+Revision 1.5 2004/05/25 18:29:33 cheshire
+Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
+so that it's also accessible to dnssd_clientshim.c (single address space) clients.
+
+Revision 1.4 2004/05/25 17:08:55 cheshire
+Fix compiler warning (doesn't make sense for function return type to be const)
+
+Revision 1.3 2004/05/21 21:41:35 cheshire
+Add TXT record building and parsing APIs
+
+Revision 1.2 2004/05/20 22:22:21 cheshire
+Enable code that was bracketed by "#if 0"
+
+Revision 1.1 2004/03/12 21:30:29 cheshire
+Build a System-Context Shared Library from mDNSCore, for the benefit of developers
+like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
+
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dns_sd.h"
+
+#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
+#pragma export on
+#endif
+
+#if defined(_WIN32)
+// disable warning "conversion from <data> to uint16_t"
+#pragma warning(disable:4244)
+#endif
+
+/*********************************************************************************************
+ *
+ * Supporting Functions
+ *
+ *********************************************************************************************/
+
+#define mdnsIsDigit(X) ((X) >= '0' && (X) <= '9')
+
+static int DomainEndsInDot(const char *dom)
+ {
+ while (dom[0] && dom[1])
+ {
+ if (dom[0] == '\\') // advance past escaped byte sequence
+ {
+ if (mdnsIsDigit(dom[1]) && mdnsIsDigit(dom[2]) && mdnsIsDigit(dom[3]))
+ dom += 4; // If "\ddd" then skip four
+ else dom += 2; // else if "\x" then skip two
+ }
+ else dom++; // else goto next character
+ }
+ return (dom[0] == '.');
+ }
+
+static uint8_t *InternalTXTRecordSearch
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ unsigned long *keylen
+ )
+ {
+ uint8_t *p = (uint8_t*)txtRecord;
+ uint8_t *e = p + txtLen;
+ *keylen = (unsigned long) strlen(key);
+ while (p<e)
+ {
+ uint8_t *x = p;
+ p += 1 + p[0];
+ if (p <= e && *keylen <= x[0] && !strncmp(key, (char*)x+1, *keylen))
+ if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
+ }
+ return(NULL);
+ }
+
+/*********************************************************************************************
+ *
+ * General Utility Functions
+ *
+ *********************************************************************************************/
+
+int DNSSD_API DNSServiceConstructFullName
+ (
+ char *fullName,
+ const char *service, /* may be NULL */
+ const char *regtype,
+ const char *domain
+ )
+ {
+ unsigned long len;
+ unsigned char c;
+ char *fn = fullName;
+ const char *s = service;
+ const char *r = regtype;
+ const char *d = domain;
+
+ if (service)
+ {
+ while(*s)
+ {
+ c = (unsigned char)*s++;
+ if (c == '.' || (c == '\\')) *fn++ = '\\'; // escape dot and backslash literals
+ else if (c <= ' ') // escape non-printable characters
+ {
+ *fn++ = '\\';
+ *fn++ = (char) ('0' + (c / 100));
+ *fn++ = (char) ('0' + (c / 10) % 10);
+ c = (unsigned char)('0' + (c % 10));
+ }
+ *fn++ = (char)c;
+ }
+ *fn++ = '.';
+ }
+
+ if (!regtype) return -1;
+ len = (unsigned long) strlen(regtype);
+ if (DomainEndsInDot(regtype)) len--;
+ if (len < 6) return -1; // regtype must be at least "x._udp" or "x._tcp"
+ if (strncmp((regtype + len - 4), "_tcp", 4) && strncmp((regtype + len - 4), "_udp", 4)) return -1;
+ while(*r) *fn++ = *r++;
+ if (!DomainEndsInDot(regtype)) *fn++ = '.';
+
+ if (!domain || !domain[0]) return -1;
+ while(*d) *fn++ = *d++;
+ if (!DomainEndsInDot(domain)) *fn++ = '.';
+ *fn = '\0';
+ return 0;
+ }
+
+/*********************************************************************************************
+ *
+ * TXT Record Construction Functions
+ *
+ *********************************************************************************************/
+
+typedef struct _TXTRecordRefRealType
+ {
+ uint8_t *buffer; // Pointer to data
+ uint16_t buflen; // Length of buffer
+ uint16_t datalen; // Length currently in use
+ uint16_t malloced; // Non-zero if buffer was allocated via malloc()
+ } TXTRecordRefRealType;
+
+#define txtRec ((TXTRecordRefRealType*)txtRecord)
+
+// The opaque storage defined in the public dns_sd.h header is 16 bytes;
+// make sure we don't exceed that.
+struct dnssd_clientlib_CompileTimeAssertionCheck
+ {
+ char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
+ };
+
+void DNSSD_API TXTRecordCreate
+ (
+ TXTRecordRef *txtRecord,
+ uint16_t bufferLen,
+ void *buffer
+ )
+ {
+ txtRec->buffer = buffer;
+ txtRec->buflen = buffer ? bufferLen : (uint16_t)0;
+ txtRec->datalen = 0;
+ txtRec->malloced = 0;
+ }
+
+void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtRecord)
+ {
+ if (txtRec->malloced) free(txtRec->buffer);
+ }
+
+DNSServiceErrorType DNSSD_API TXTRecordSetValue
+ (
+ TXTRecordRef *txtRecord,
+ const char *key,
+ uint8_t valueSize,
+ const void *value
+ )
+ {
+ uint8_t *start, *p;
+ const char *k;
+ unsigned long keysize, keyvalsize;
+
+ for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid);
+ keysize = (unsigned long)(k - key);
+ keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0);
+ if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid);
+ (void)TXTRecordRemoveValue(txtRecord, key);
+ if (txtRec->datalen + keyvalsize > txtRec->buflen)
+ {
+ unsigned char *newbuf;
+ unsigned long newlen = txtRec->datalen + keyvalsize;
+ if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid);
+ newbuf = malloc((size_t)newlen);
+ if (!newbuf) return(kDNSServiceErr_NoMemory);
+ memcpy(newbuf, txtRec->buffer, txtRec->datalen);
+ if (txtRec->malloced) free(txtRec->buffer);
+ txtRec->buffer = newbuf;
+ txtRec->buflen = (uint16_t)(newlen);
+ txtRec->malloced = 1;
+ }
+ start = txtRec->buffer + txtRec->datalen;
+ p = start + 1;
+ memcpy(p, key, keysize);
+ p += keysize;
+ if (value)
+ {
+ *p++ = '=';
+ memcpy(p, value, valueSize);
+ p += valueSize;
+ }
+ *start = (uint8_t)(p - start - 1);
+ txtRec->datalen += p - start;
+ return(kDNSServiceErr_NoError);
+ }
+
+DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
+ (
+ TXTRecordRef *txtRecord,
+ const char *key
+ )
+ {
+ unsigned long keylen, itemlen, remainder;
+ uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen);
+ if (!item) return(kDNSServiceErr_NoSuchKey);
+ itemlen = (unsigned long)(1 + item[0]);
+ remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen));
+ // Use memmove because memcpy behaviour is undefined for overlapping regions
+ memmove(item, item + itemlen, remainder);
+ txtRec->datalen -= itemlen;
+ return(kDNSServiceErr_NoError);
+ }
+
+uint16_t DNSSD_API TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); }
+const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); }
+
+/*********************************************************************************************
+ *
+ * TXT Record Parsing Functions
+ *
+ *********************************************************************************************/
+
+int DNSSD_API TXTRecordContainsKey
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key
+ )
+ {
+ unsigned long keylen;
+ return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0);
+ }
+
+const void * DNSSD_API TXTRecordGetValuePtr
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ uint8_t *valueLen
+ )
+ {
+ unsigned long keylen;
+ uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen);
+ if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL
+ *valueLen = (uint8_t)(item[0] - (keylen + 1));
+ return (item + 1 + keylen + 1);
+ }
+
+uint16_t DNSSD_API TXTRecordGetCount
+ (
+ uint16_t txtLen,
+ const void *txtRecord
+ )
+ {
+ uint16_t count = 0;
+ uint8_t *p = (uint8_t*)txtRecord;
+ uint8_t *e = p + txtLen;
+ while (p<e) { p += 1 + p[0]; count++; }
+ return((p>e) ? (uint16_t)0 : count);
+ }
+
+DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ uint16_t index,
+ uint16_t keyBufLen,
+ char *key,
+ uint8_t *valueLen,
+ const void **value
+ )
+ {
+ uint16_t count = 0;
+ uint8_t *p = (uint8_t*)txtRecord;
+ uint8_t *e = p + txtLen;
+ while (p<e && count<index) { p += 1 + p[0]; count++; } // Find requested item
+ if (p<e && p + 1 + p[0] <= e) // If valid
+ {
+ uint8_t *x = p+1;
+ unsigned long len = 0;
+ e = p + 1 + p[0];
+ while (x+len<e && x[len] != '=') len++;
+ if (len >= keyBufLen) return(kDNSServiceErr_NoMemory);
+ memcpy(key, x, len);
+ key[len] = 0;
+ if (x+len<e) // If we found '='
+ {
+ *value = x + len + 1;
+ *valueLen = (uint8_t)(p[0] - (len + 1));
+ }
+ else
+ {
+ *value = NULL;
+ *valueLen = 0;
+ }
+ return(kDNSServiceErr_NoError);
+ }
+ return(kDNSServiceErr_Invalid);
+ }
diff --git a/usr/src/lib/libdns_sd/common/dnssd_clientstub.c b/usr/src/lib/libdns_sd/common/dnssd_clientstub.c
new file mode 100644
index 0000000000..2a22a0e22f
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/dnssd_clientstub.c
@@ -0,0 +1,1249 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+
+$Log: dnssd_clientstub.c,v $
+Revision 1.53 2006/09/07 04:43:12 herscher
+Fix compile error on Win32 platform by moving inclusion of syslog.h
+
+Revision 1.52 2006/08/15 23:04:21 mkrochma
+<rdar://problem/4090354> Client should be able to specify service name w/o callback
+
+Revision 1.51 2006/07/24 23:45:55 cheshire
+<rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
+
+Revision 1.50 2006/06/28 08:22:27 cheshire
+<rdar://problem/4605264> dnssd_clientstub.c needs to report unlink failures in syslog
+
+Revision 1.49 2006/06/28 07:58:59 cheshire
+Minor textual tidying
+
+Revision 1.48 2005/06/30 18:01:00 shersche
+<rdar://problem/4096913> Clients shouldn't wait ten seconds to connect to mDNSResponder
+
+Revision 1.47 2005/03/31 02:19:56 cheshire
+<rdar://problem/4021486> Fix build warnings
+Reviewed by: Scott Herscher
+
+Revision 1.46 2005/03/21 00:39:31 shersche
+<rdar://problem/4021486> Fix build warnings on Win32 platform
+
+Revision 1.45 2005/02/01 01:25:06 shersche
+Define sleep() to be Sleep() for Windows compatibility
+
+Revision 1.44 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
+Revision 1.43 2005/01/27 00:02:29 cheshire
+<rdar://problem/3947461> Handle case where client runs before daemon has finished launching
+
+Revision 1.42 2005/01/11 02:01:02 shersche
+Use dnssd_close() rather than close() for Windows compatibility
+
+Revision 1.41 2004/12/23 17:34:26 ksekar
+<rdar://problem/3931319> Calls leak sockets if mDNSResponder is not running
+
+Revision 1.40 2004/11/23 03:39:47 cheshire
+Let interface name/index mapping capability live directly in JNISupport.c,
+instead of having to call through to the daemon via IPC to get this information.
+
+Revision 1.39 2004/11/12 03:22:00 rpantos
+rdar://problem/3809541 Add DNSSDMapIfIndexToName, DNSSDMapNameToIfIndex.
+
+Revision 1.38 2004/11/02 02:51:23 cheshire
+<rdar://problem/3526342> Remove overly-restrictive flag checks
+
+Revision 1.37 2004/10/14 01:43:35 cheshire
+Fix opaque port passing problem
+
+Revision 1.36 2004/10/06 02:22:19 cheshire
+Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
+
+Revision 1.35 2004/10/01 22:15:55 rpantos
+rdar://problem/3824265: Replace APSL in client lib with BSD license.
+
+Revision 1.34 2004/09/17 22:36:13 cheshire
+Add comment explaining that deliver_request frees the message it sends
+
+Revision 1.33 2004/09/17 01:17:31 ksekar
+Remove double-free of msg header, freed automatically by deliver_request()
+
+Revision 1.32 2004/09/17 01:08:55 cheshire
+Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
+ The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
+ declared in that file are ONLY appropriate to single-address-space embedded applications.
+ For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
+
+Revision 1.31 2004/09/16 23:37:19 cheshire
+Free hdr before returning
+
+Revision 1.30 2004/09/16 23:14:24 cheshire
+Changes for Windows compatibility
+
+Revision 1.29 2004/09/16 21:46:38 ksekar
+<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
+
+Revision 1.28 2004/08/11 17:10:04 cheshire
+Fix signed/unsigned warnings
+
+Revision 1.27 2004/08/11 00:54:16 cheshire
+Change "hdr->op.request_op" to just "hdr->op"
+
+Revision 1.26 2004/07/26 06:07:27 shersche
+fix bugs when using an error socket to communicate with the daemon
+
+Revision 1.25 2004/07/26 05:54:02 shersche
+DNSServiceProcessResult() returns NoError if socket read returns EWOULDBLOCK
+
+Revision 1.24 2004/07/20 06:46:21 shersche
+<rdar://problem/3730123> fix endless loop in read_all() if recv returns 0
+Bug #: 3730123
+
+Revision 1.23 2004/06/29 00:48:38 cheshire
+Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions;
+use an explicit while() loop instead.
+
+Revision 1.22 2004/06/26 03:16:34 shersche
+clean up warning messages on Win32 platform
+
+Submitted by: herscher
+
+Revision 1.21 2004/06/18 04:53:56 rpantos
+Use platform layer for socket types. Introduce USE_TCP_LOOPBACK. Remove dependency on mDNSEmbeddedAPI.h.
+
+Revision 1.20 2004/06/12 00:50:22 cheshire
+Changes for Windows compatibility
+
+Revision 1.19 2004/05/25 18:29:33 cheshire
+Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c,
+so that it's also accessible to dnssd_clientshim.c (single address space) clients.
+
+Revision 1.18 2004/05/18 23:51:27 cheshire
+Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
+
+Revision 1.17 2004/05/06 18:42:58 ksekar
+General dns_sd.h API cleanup, including the following radars:
+<rdar://problem/3592068>: Remove flags with zero value
+<rdar://problem/3479569>: Passing in NULL causes a crash.
+
+Revision 1.16 2004/03/12 22:00:37 cheshire
+Added: #include <sys/socket.h>
+
+Revision 1.15 2004/01/20 18:36:29 ksekar
+Propagated Libinfo fix for <rdar://problem/3483971>: SU:
+DNSServiceUpdateRecord() doesn't allow you to update the TXT record
+into TOT mDNSResponder.
+
+Revision 1.14 2004/01/19 22:39:17 cheshire
+Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux;
+use an explicit while() loop instead. (In any case, this should only make a difference
+with non-blocking sockets, which we don't use on the client side right now.)
+
+Revision 1.13 2004/01/19 21:46:52 cheshire
+Fix compiler warning
+
+Revision 1.12 2003/12/23 20:46:47 ksekar
+<rdar://problem/3497428>: sync dnssd files between libinfo & mDNSResponder
+
+Revision 1.11 2003/12/08 21:11:42 rpantos
+Changes necessary to support mDNSResponder on Linux.
+
+Revision 1.10 2003/10/13 23:50:53 ksekar
+Updated dns_sd clientstub files to bring copies in synch with
+top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed,
+and comments in dns_sd.h are improved.
+
+Revision 1.9 2003/08/15 21:30:39 cheshire
+Bring up to date with LibInfo version
+
+Revision 1.8 2003/08/13 23:54:52 ksekar
+Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640
+
+Revision 1.7 2003/08/12 19:56:25 cheshire
+Update to APSL 2.0
+
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "dnssd_ipc.h"
+
+#if defined(_WIN32)
+
+#include <winsock2.h>
+#include <windows.h>
+
+#define sockaddr_mdns sockaddr_in
+#define AF_MDNS AF_INET
+
+// disable warning: "'type cast' : from data pointer 'void *' to function pointer"
+#pragma warning(disable:4055)
+
+// disable warning: "nonstandard extension, function/data pointer conversion in expression"
+#pragma warning(disable:4152)
+
+extern BOOL IsSystemServiceDisabled();
+
+#define sleep(X) Sleep((X) * 1000)
+
+static int g_initWinsock = 0;
+
+#else
+
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <syslog.h>
+
+#define sockaddr_mdns sockaddr_un
+#define AF_MDNS AF_LOCAL
+
+#endif
+
+// <rdar://problem/4096913> Specifies how many times we'll try and connect to the
+// server.
+
+#define DNSSD_CLIENT_MAXTRIES 4
+
+#define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
+// error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
+// last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
+
+// general utility functions
+typedef struct _DNSServiceRef_t
+ {
+ dnssd_sock_t sockfd; // connected socket between client and daemon
+ uint32_t op; // request_op_t or reply_op_t
+ process_reply_callback process_reply;
+ void *app_callback;
+ void *app_context;
+ uint32_t max_index; //largest assigned record index - 0 if no additl. recs registered
+ } _DNSServiceRef_t;
+
+typedef struct _DNSRecordRef_t
+ {
+ void *app_context;
+ DNSServiceRegisterRecordReply app_callback;
+ DNSRecordRef recref;
+ uint32_t record_index; // index is unique to the ServiceDiscoveryRef
+ DNSServiceRef sdr;
+ } _DNSRecordRef_t;
+
+// exported functions
+
+// write len bytes. return 0 on success, -1 on error
+static int write_all(dnssd_sock_t sd, char *buf, int len)
+ {
+ // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
+ //if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
+ while (len)
+ {
+ ssize_t num_written = send(sd, buf, len, 0);
+ if (num_written < 0 || num_written > len) return -1;
+ buf += num_written;
+ len -= num_written;
+ }
+ return 0;
+ }
+
+// read len bytes. return 0 on success, -1 on error
+static int read_all(dnssd_sock_t sd, char *buf, int len)
+ {
+ // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
+ //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1;
+ while (len)
+ {
+ ssize_t num_read = recv(sd, buf, len, 0);
+ if ((num_read == -1) && (errno == EINTR))
+ continue;
+ if ((num_read < 0) || (num_read > len)) return -1;
+ // Return error -2 when no data received and errno is not set
+ if (num_read == 0) return -2;
+ buf += num_read;
+ len -= num_read;
+ }
+ return 0;
+ }
+
+/* create_hdr
+ *
+ * allocate and initialize an ipc message header. value of len should initially be the
+ * length of the data, and is set to the value of the data plus the header. data_start
+ * is set to point to the beginning of the data section. reuse_socket should be non-zero
+ * for calls that can receive an immediate error return value on their primary socket.
+ * if zero, the path to a control socket is appended at the beginning of the message buffer.
+ * data_start is set past this string.
+ */
+
+static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int reuse_socket)
+ {
+ char *msg = NULL;
+ ipc_msg_hdr *hdr;
+ int datalen;
+#if !defined(USE_TCP_LOOPBACK)
+ char ctrl_path[256];
+#endif
+
+ if (!reuse_socket)
+ {
+#if defined(USE_TCP_LOOPBACK)
+ *len += 2; // Allocate space for two-byte port number
+#else
+ struct timeval time;
+ if (gettimeofday(&time, NULL) < 0) return NULL;
+ sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
+ (unsigned long)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec));
+ *len += strlen(ctrl_path) + 1;
+#endif
+ }
+
+ datalen = (int) *len;
+ *len += sizeof(ipc_msg_hdr);
+
+ // write message to buffer
+ msg = malloc(*len);
+ if (!msg) return NULL;
+
+ bzero(msg, *len);
+ hdr = (void *)msg;
+ hdr->datalen = datalen;
+ hdr->version = VERSION;
+ hdr->op = op;
+ if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET;
+ *data_start = msg + sizeof(ipc_msg_hdr);
+#if defined(USE_TCP_LOOPBACK)
+ // Put dummy data in for the port, since we don't know what
+ // it is yet. The data will get filled in before we
+ // send the message. This happens in deliver_request().
+ if (!reuse_socket) put_short(0, data_start);
+#else
+ if (!reuse_socket) put_string(ctrl_path, data_start);
+#endif
+ return hdr;
+ }
+
+ // return a connected service ref (deallocate with DNSServiceRefDeallocate)
+static DNSServiceRef connect_to_server(void)
+ {
+ dnssd_sockaddr_t saddr;
+ DNSServiceRef sdr;
+ int NumTries = 0;
+
+#if defined(_WIN32)
+ if (!g_initWinsock)
+ {
+ WSADATA wsaData;
+ DNSServiceErrorType err;
+
+ g_initWinsock = 1;
+
+ err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
+
+ if (err != 0) return NULL;
+ }
+
+ // <rdar://problem/4096913> If the system service is disabled, we only want to try
+ // to connect once
+
+ if ( IsSystemServiceDisabled() )
+ {
+ NumTries = DNSSD_CLIENT_MAXTRIES;
+ }
+
+#endif
+
+ sdr = malloc(sizeof(_DNSServiceRef_t));
+ if (!sdr) return(NULL);
+ sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0);
+ if (sdr->sockfd == dnssd_InvalidSocket) { free(sdr); return NULL; }
+#if defined(USE_TCP_LOOPBACK)
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
+ saddr.sin_port = htons(MDNS_TCP_SERVERPORT);
+#else
+ saddr.sun_family = AF_LOCAL;
+ strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
+#endif
+ while (1)
+ {
+ int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
+ if (!err) break; // If we succeeded, return sdr
+ // If we failed, then it may be because the daemon is still launching.
+ // This can happen for processes that launch early in the boot process, while the
+ // daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
+ // If, after four seconds, we still can't connect to the daemon,
+ // then we give up and return a failure code.
+ if (++NumTries < DNSSD_CLIENT_MAXTRIES)
+ sleep(1); // Sleep a bit, then try again
+ else
+ {
+ dnssd_close(sdr->sockfd);
+ sdr->sockfd = dnssd_InvalidSocket;
+ free(sdr);
+ return NULL;
+ }
+ }
+ return sdr;
+ }
+
+static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd)
+ {
+ ipc_msg_hdr *hdr = msg;
+ uint32_t datalen = hdr->datalen;
+ dnssd_sockaddr_t caddr, daddr; // (client and daemon address structs)
+ char *const data = (char *)msg + sizeof(ipc_msg_hdr);
+ dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
+ int ret;
+ dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
+ DNSServiceErrorType err = kDNSServiceErr_Unknown;
+
+ if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown;
+
+ if (!reuse_sd)
+ {
+ // setup temporary error socket
+ if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) < 0)
+ goto cleanup;
+ bzero(&caddr, sizeof(caddr));
+
+#if defined(USE_TCP_LOOPBACK)
+ {
+ union { uint16_t s; u_char b[2]; } port;
+ caddr.sin_family = AF_INET;
+ caddr.sin_port = 0;
+ caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
+ ret = bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr));
+ if (ret < 0) goto cleanup;
+ if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup;
+ listen(listenfd, 1);
+ port.s = caddr.sin_port;
+ data[0] = port.b[0]; // don't switch the byte order, as the
+ data[1] = port.b[1]; // daemon expects it in network byte order
+ }
+#else
+ {
+ mode_t mask = umask(0);
+ caddr.sun_family = AF_LOCAL;
+// According to Stevens (section 3.2), there is no portable way to
+// determine whether sa_len is defined on a particular platform.
+#ifndef NOT_HAVE_SA_LEN
+ caddr.sun_len = sizeof(struct sockaddr_un);
+#endif
+ //syslog(LOG_WARNING, "deliver_request: creating UDS: %s\n", data);
+ strcpy(caddr.sun_path, data);
+ ret = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
+ umask(mask);
+ if (ret < 0) goto cleanup;
+ listen(listenfd, 1);
+ }
+#endif
+ }
+
+ ConvertHeaderBytes(hdr);
+ //syslog(LOG_WARNING, "deliver_request writing %ld bytes\n", datalen + sizeof(ipc_msg_hdr));
+ //syslog(LOG_WARNING, "deliver_request name is %s\n", (char *)msg + sizeof(ipc_msg_hdr));
+ if (write_all(sdr->sockfd, msg, datalen + sizeof(ipc_msg_hdr)) < 0)
+ goto cleanup;
+ free(msg);
+ msg = NULL;
+
+ if (reuse_sd) errsd = sdr->sockfd;
+ else
+ {
+ //syslog(LOG_WARNING, "deliver_request: accept\n");
+ len = sizeof(daddr);
+ errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
+ //syslog(LOG_WARNING, "deliver_request: accept returned %d\n", errsd);
+ if (errsd < 0) goto cleanup;
+ }
+
+ if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
+ err = kDNSServiceErr_Unknown;
+ else
+ err = ntohl(err);
+
+ //syslog(LOG_WARNING, "deliver_request: retrieved error code %d\n", err);
+
+cleanup:
+ if (!reuse_sd)
+ {
+ if (listenfd > 0) dnssd_close(listenfd);
+ if (errsd > 0) dnssd_close(errsd);
+#if !defined(USE_TCP_LOOPBACK)
+ // syslog(LOG_WARNING, "deliver_request: removing UDS: %s\n", data);
+ if (unlink(data) != 0)
+ syslog(LOG_WARNING, "WARNING: unlink(\"%s\") failed errno %d (%s)", data, errno, strerror(errno));
+ // else syslog(LOG_WARNING, "deliver_request: removed UDS: %s\n", data);
+#endif
+ }
+ if (msg) free(msg);
+ return err;
+ }
+
+int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
+ {
+ if (!sdRef) return -1;
+ return (int) sdRef->sockfd;
+ }
+
+// handle reply from server, calling application client callback. If there is no reply
+// from the daemon on the socket contained in sdRef, the call will block.
+DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
+ {
+ ipc_msg_hdr hdr;
+ char *data;
+ int rderr;
+
+ if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply)
+ return kDNSServiceErr_BadReference;
+
+ rderr = read_all(sdRef->sockfd, (void *)&hdr, sizeof(hdr));
+ if (rderr < 0) {
+ // return NoError on EWOULDBLOCK. This will handle the case
+ // where a non-blocking socket is told there is data, but
+ // it was a false positive. Can check errno when error
+ // code returned is -1
+ if ((rderr == -1) && (dnssd_errno() == dnssd_EWOULDBLOCK))
+ return kDNSServiceErr_NoError;
+ return kDNSServiceErr_Unknown;
+ }
+ ConvertHeaderBytes(&hdr);
+ if (hdr.version != VERSION)
+ return kDNSServiceErr_Incompatible;
+ data = malloc(hdr.datalen);
+ if (!data) return kDNSServiceErr_NoMemory;
+ if (read_all(sdRef->sockfd, data, hdr.datalen) < 0)
+ return kDNSServiceErr_Unknown;
+ sdRef->process_reply(sdRef, &hdr, data);
+ free(data);
+ return kDNSServiceErr_NoError;
+ }
+
+void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
+ {
+ if (!sdRef) return;
+ if (sdRef->sockfd > 0) dnssd_close(sdRef->sockfd);
+ free(sdRef);
+ }
+
+static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
+ {
+ DNSServiceFlags flags;
+ char fullname[kDNSServiceMaxDomainName];
+ char target[kDNSServiceMaxDomainName];
+ uint16_t txtlen;
+ union { uint16_t s; u_char b[2]; } port;
+ uint32_t ifi;
+ DNSServiceErrorType err;
+ unsigned char *txtrecord;
+ int str_error = 0;
+ (void)hdr; //unused
+
+ flags = get_flags(&data);
+ ifi = get_long(&data);
+ err = get_error_code(&data);
+ if (get_string(&data, fullname, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (get_string(&data, target, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ port.b[0] = *data++;
+ port.b[1] = *data++;
+ txtlen = get_short(&data);
+ txtrecord = (unsigned char *)get_rdata(&data, txtlen);
+
+ if (!err && str_error) err = kDNSServiceErr_Unknown;
+ ((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port.s, txtlen, txtrecord, sdr->app_context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceResolve
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ DNSServiceResolveReply callBack,
+ void *context
+ )
+ {
+ char *msg = NULL, *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr;
+ DNSServiceRef sdr;
+ DNSServiceErrorType err;
+
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ *sdRef = NULL;
+
+ if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
+
+ // calculate total message length
+ len = sizeof(flags);
+ len += sizeof(interfaceIndex);
+ len += strlen(name) + 1;
+ len += strlen(regtype) + 1;
+ len += strlen(domain) + 1;
+
+ hdr = create_hdr(resolve_request, &len, &ptr, 1);
+ if (!hdr) goto error;
+ msg = (void *)hdr;
+
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+ put_string(name, &ptr);
+ put_string(regtype, &ptr);
+ put_string(domain, &ptr);
+
+ sdr = connect_to_server();
+ if (!sdr) goto error;
+ err = deliver_request(msg, sdr, 1);
+ if (err)
+ {
+ DNSServiceRefDeallocate(sdr);
+ return err;
+ }
+ sdr->op = resolve_request;
+ sdr->process_reply = handle_resolve_response;
+ sdr->app_callback = callBack;
+ sdr->app_context = context;
+ *sdRef = sdr;
+
+ return err;
+
+error:
+ if (msg) free(msg);
+ if (*sdRef) { free(*sdRef); *sdRef = NULL; }
+ return kDNSServiceErr_Unknown;
+ }
+
+static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
+ {
+ DNSServiceFlags flags;
+ uint32_t interfaceIndex, ttl;
+ DNSServiceErrorType errorCode;
+ char name[kDNSServiceMaxDomainName];
+ uint16_t rrtype, rrclass, rdlen;
+ char *rdata;
+ int str_error = 0;
+ (void)hdr;//Unused
+
+ flags = get_flags(&data);
+ interfaceIndex = get_long(&data);
+ errorCode = get_error_code(&data);
+ if (get_string(&data, name, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ rrtype = get_short(&data);
+ rrclass = get_short(&data);
+ rdlen = get_short(&data);
+ rdata = get_rdata(&data, rdlen);
+ ttl = get_long(&data);
+
+ if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
+ ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass,
+ rdlen, rdata, ttl, sdr->app_context);
+ return;
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ DNSServiceQueryRecordReply callBack,
+ void *context
+ )
+ {
+ char *msg = NULL, *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr;
+ DNSServiceRef sdr;
+ DNSServiceErrorType err;
+
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ *sdRef = NULL;
+
+ if (!name) name = "\0";
+
+ // calculate total message length
+ len = sizeof(flags);
+ len += sizeof(uint32_t); //interfaceIndex
+ len += strlen(name) + 1;
+ len += 2 * sizeof(uint16_t); // rrtype, rrclass
+
+ hdr = create_hdr(query_request, &len, &ptr, 1);
+ if (!hdr) goto error;
+ msg = (void *)hdr;
+
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+ put_string(name, &ptr);
+ put_short(rrtype, &ptr);
+ put_short(rrclass, &ptr);
+
+ sdr = connect_to_server();
+ if (!sdr) goto error;
+ err = deliver_request(msg, sdr, 1);
+ if (err)
+ {
+ DNSServiceRefDeallocate(sdr);
+ return err;
+ }
+
+ sdr->op = query_request;
+ sdr->process_reply = handle_query_response;
+ sdr->app_callback = callBack;
+ sdr->app_context = context;
+ *sdRef = sdr;
+ return err;
+
+error:
+ if (msg) free(msg);
+ if (*sdRef) { free(*sdRef); *sdRef = NULL; }
+ return kDNSServiceErr_Unknown;
+ }
+
+static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
+ {
+ DNSServiceFlags flags;
+ uint32_t interfaceIndex;
+ DNSServiceErrorType errorCode;
+ char replyName[256], replyType[kDNSServiceMaxDomainName],
+ replyDomain[kDNSServiceMaxDomainName];
+ int str_error = 0;
+ (void)hdr;//Unused
+
+ flags = get_flags(&data);
+ interfaceIndex = get_long(&data);
+ errorCode = get_error_code(&data);
+ if (get_string(&data, replyName, 256) < 0) str_error = 1;
+ if (get_string(&data, replyType, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (get_string(&data, replyDomain, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
+ ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceBrowse
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *regtype,
+ const char *domain,
+ DNSServiceBrowseReply callBack,
+ void *context
+ )
+ {
+ char *msg = NULL, *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr;
+ DNSServiceRef sdr;
+ DNSServiceErrorType err;
+
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ *sdRef = NULL;
+
+ if (!domain) domain = "";
+
+ len = sizeof(flags);
+ len += sizeof(interfaceIndex);
+ len += strlen(regtype) + 1;
+ len += strlen(domain) + 1;
+
+ hdr = create_hdr(browse_request, &len, &ptr, 1);
+ if (!hdr) goto error;
+ msg = (char *)hdr;
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+ put_string(regtype, &ptr);
+ put_string(domain, &ptr);
+
+ sdr = connect_to_server();
+ if (!sdr) goto error;
+ err = deliver_request(msg, sdr, 1);
+ if (err)
+ {
+ DNSServiceRefDeallocate(sdr);
+ return err;
+ }
+ sdr->op = browse_request;
+ sdr->process_reply = handle_browse_response;
+ sdr->app_callback = callBack;
+ sdr->app_context = context;
+ *sdRef = sdr;
+ return err;
+
+error:
+ if (msg) free(msg);
+ if (*sdRef) { free(*sdRef); *sdRef = NULL; }
+ return kDNSServiceErr_Unknown;
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
+ (
+ DNSServiceFlags flags,
+ const char *domain
+ )
+ {
+ DNSServiceRef sdr;
+ DNSServiceErrorType err;
+ char *ptr = NULL;
+ size_t len = sizeof(flags) + strlen(domain) + 1;
+ ipc_msg_hdr *hdr = create_hdr(setdomain_request, &len, &ptr, 1);
+
+ if (!hdr) return kDNSServiceErr_Unknown;
+ put_flags(flags, &ptr);
+ put_string(domain, &ptr);
+
+ sdr = connect_to_server();
+ if (!sdr) { free(hdr); return kDNSServiceErr_Unknown; }
+ err = deliver_request((char *)hdr, sdr, 1); // deliver_request frees the message for us
+ DNSServiceRefDeallocate(sdr);
+ return err;
+ }
+
+
+static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
+ {
+ DNSServiceFlags flags;
+ uint32_t interfaceIndex;
+ DNSServiceErrorType errorCode;
+ char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
+ int str_error = 0;
+ (void)hdr;//Unused
+
+ flags = get_flags(&data);
+ interfaceIndex = get_long(&data);
+ errorCode = get_error_code(&data);
+ if (get_string(&data, name, 256) < 0) str_error = 1;
+ if (get_string(&data, regtype, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown;
+ ((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceRegister
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ const char *host,
+ uint16_t PortInNetworkByteOrder,
+ uint16_t txtLen,
+ const void *txtRecord,
+ DNSServiceRegisterReply callBack,
+ void *context
+ )
+ {
+ char *msg = NULL, *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr;
+ DNSServiceRef sdr;
+ DNSServiceErrorType err;
+ union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
+
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ *sdRef = NULL;
+
+ if (!name) name = "";
+ if (!regtype) return kDNSServiceErr_BadParam;
+ if (!domain) domain = "";
+ if (!host) host = "";
+ if (!txtRecord) txtRecord = (void*)"";
+
+ // auto-name must also have auto-rename
+ if (!name[0] && (flags & kDNSServiceFlagsNoAutoRename))
+ return kDNSServiceErr_BadParam;
+
+ // no callback must have auto-rename
+ if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam;
+
+ len = sizeof(DNSServiceFlags);
+ len += sizeof(uint32_t); // interfaceIndex
+ len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
+ len += 2 * sizeof(uint16_t); // port, txtLen
+ len += txtLen;
+
+ hdr = create_hdr(reg_service_request, &len, &ptr, 1);
+ if (!hdr) goto error;
+ if (!callBack) hdr->flags |= IPC_FLAGS_NOREPLY;
+ msg = (char *)hdr;
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+ put_string(name, &ptr);
+ put_string(regtype, &ptr);
+ put_string(domain, &ptr);
+ put_string(host, &ptr);
+ *ptr++ = port.b[0];
+ *ptr++ = port.b[1];
+ put_short(txtLen, &ptr);
+ put_rdata(txtLen, txtRecord, &ptr);
+
+ sdr = connect_to_server();
+ if (!sdr) goto error;
+ err = deliver_request(msg, sdr, 1);
+ if (err)
+ {
+ DNSServiceRefDeallocate(sdr);
+ return err;
+ }
+
+ sdr->op = reg_service_request;
+ sdr->process_reply = callBack ? handle_regservice_response : NULL;
+ sdr->app_callback = callBack;
+ sdr->app_context = context;
+ *sdRef = sdr;
+
+ return err;
+
+error:
+ if (msg) free(msg);
+ if (*sdRef) { free(*sdRef); *sdRef = NULL; }
+ return kDNSServiceErr_Unknown;
+ }
+
+static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
+ {
+ DNSServiceFlags flags;
+ uint32_t interfaceIndex;
+ DNSServiceErrorType err;
+ char domain[kDNSServiceMaxDomainName];
+ int str_error = 0;
+ (void)hdr;//Unused
+
+ flags = get_flags(&data);
+ interfaceIndex = get_long(&data);
+ err = get_error_code(&data);
+ if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1;
+ if (!err && str_error) err = kDNSServiceErr_Unknown;
+ ((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceDomainEnumReply callBack,
+ void *context
+ )
+ {
+ char *msg = NULL, *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr;
+ DNSServiceRef sdr;
+ DNSServiceErrorType err;
+ int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
+ int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
+ if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
+
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ *sdRef = NULL;
+
+ len = sizeof(DNSServiceFlags);
+ len += sizeof(uint32_t);
+
+ hdr = create_hdr(enumeration_request, &len, &ptr, 1);
+ if (!hdr) goto error;
+ msg = (void *)hdr;
+
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+
+ sdr = connect_to_server();
+ if (!sdr) goto error;
+ err = deliver_request(msg, sdr, 1);
+ if (err)
+ {
+ DNSServiceRefDeallocate(sdr);
+ return err;
+ }
+
+ sdr->op = enumeration_request;
+ sdr->process_reply = handle_enumeration_response;
+ sdr->app_callback = callBack;
+ sdr->app_context = context;
+ *sdRef = sdr;
+ return err;
+
+error:
+ if (msg) free(msg);
+ if (*sdRef) { free(*sdRef); *sdRef = NULL; }
+ return kDNSServiceErr_Unknown;
+ }
+
+static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data)
+ {
+ DNSServiceFlags flags;
+ uint32_t interfaceIndex;
+ DNSServiceErrorType errorCode;
+ DNSRecordRef rref = hdr->client_context.context;
+
+ if (sdr->op != connection)
+ {
+ rref->app_callback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->app_context);
+ return;
+ }
+ flags = get_flags(&data);
+ interfaceIndex = get_long(&data);
+ errorCode = get_error_code(&data);
+
+ rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
+ {
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ *sdRef = connect_to_server();
+ if (!*sdRef)
+ return kDNSServiceErr_Unknown;
+ (*sdRef)->op = connection;
+ (*sdRef)->process_reply = handle_regrecord_response;
+ return 0;
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ DNSServiceRegisterRecordReply callBack,
+ void *context
+ )
+ {
+ char *msg = NULL, *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr = NULL;
+ DNSServiceRef tmp = NULL;
+ DNSRecordRef rref = NULL;
+ int f1 = (flags & kDNSServiceFlagsShared) != 0;
+ int f2 = (flags & kDNSServiceFlagsUnique) != 0;
+ if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
+
+ if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0)
+ return kDNSServiceErr_BadReference;
+ *RecordRef = NULL;
+
+ len = sizeof(DNSServiceFlags);
+ len += 2 * sizeof(uint32_t); // interfaceIndex, ttl
+ len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
+ len += strlen(fullname) + 1;
+ len += rdlen;
+
+ hdr = create_hdr(reg_record_request, &len, &ptr, 0);
+ if (!hdr) goto error;
+ msg = (char *)hdr;
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+ put_string(fullname, &ptr);
+ put_short(rrtype, &ptr);
+ put_short(rrclass, &ptr);
+ put_short(rdlen, &ptr);
+ put_rdata(rdlen, rdata, &ptr);
+ put_long(ttl, &ptr);
+
+ rref = malloc(sizeof(_DNSRecordRef_t));
+ if (!rref) goto error;
+ rref->app_context = context;
+ rref->app_callback = callBack;
+ rref->record_index = sdRef->max_index++;
+ rref->sdr = sdRef;
+ *RecordRef = rref;
+ hdr->client_context.context = rref;
+ hdr->reg_index = rref->record_index;
+
+ return deliver_request(msg, sdRef, 0);
+
+error:
+ if (rref) free(rref);
+ if (tmp) free(tmp);
+ if (hdr) free(hdr);
+ return kDNSServiceErr_Unknown;
+ }
+
+//sdRef returned by DNSServiceRegister()
+DNSServiceErrorType DNSSD_API DNSServiceAddRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ DNSServiceFlags flags,
+ uint16_t rrtype,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl
+ )
+ {
+ ipc_msg_hdr *hdr;
+ size_t len = 0;
+ char *ptr;
+ DNSRecordRef rref;
+
+ if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef)
+ return kDNSServiceErr_BadReference;
+ *RecordRef = NULL;
+
+ len += 2 * sizeof(uint16_t); //rrtype, rdlen
+ len += rdlen;
+ len += sizeof(uint32_t);
+ len += sizeof(DNSServiceFlags);
+
+ hdr = create_hdr(add_record_request, &len, &ptr, 0);
+ if (!hdr) return kDNSServiceErr_Unknown;
+ put_flags(flags, &ptr);
+ put_short(rrtype, &ptr);
+ put_short(rdlen, &ptr);
+ put_rdata(rdlen, rdata, &ptr);
+ put_long(ttl, &ptr);
+
+ rref = malloc(sizeof(_DNSRecordRef_t));
+ if (!rref) goto error;
+ rref->app_context = NULL;
+ rref->app_callback = NULL;
+ rref->record_index = sdRef->max_index++;
+ rref->sdr = sdRef;
+ *RecordRef = rref;
+ hdr->client_context.context = rref;
+ hdr->reg_index = rref->record_index;
+ return deliver_request((char *)hdr, sdRef, 0);
+
+error:
+ if (hdr) free(hdr);
+ if (rref) free(rref);
+ if (*RecordRef) *RecordRef = NULL;
+ return kDNSServiceErr_Unknown;
+}
+
+//DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
+DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
+ DNSServiceFlags flags,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl
+ )
+ {
+ ipc_msg_hdr *hdr;
+ size_t len = 0;
+ char *ptr;
+
+ if (!sdRef) return kDNSServiceErr_BadReference;
+
+ len += sizeof(uint16_t);
+ len += rdlen;
+ len += sizeof(uint32_t);
+ len += sizeof(DNSServiceFlags);
+
+ hdr = create_hdr(update_record_request, &len, &ptr, 0);
+ if (!hdr) return kDNSServiceErr_Unknown;
+ hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX;
+ put_flags(flags, &ptr);
+ put_short(rdlen, &ptr);
+ put_rdata(rdlen, rdata, &ptr);
+ put_long(ttl, &ptr);
+ return deliver_request((char *)hdr, sdRef, 0);
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
+ DNSServiceFlags flags
+ )
+ {
+ ipc_msg_hdr *hdr;
+ size_t len = 0;
+ char *ptr;
+ DNSServiceErrorType err;
+
+ if (!sdRef || !RecordRef || !sdRef->max_index)
+ return kDNSServiceErr_BadReference;
+
+ len += sizeof(flags);
+ hdr = create_hdr(remove_record_request, &len, &ptr, 0);
+ if (!hdr) return kDNSServiceErr_Unknown;
+ hdr->reg_index = RecordRef->record_index;
+ put_flags(flags, &ptr);
+ err = deliver_request((char *)hdr, sdRef, 0);
+ if (!err) free(RecordRef);
+ return err;
+ }
+
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
+ (
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata
+ )
+ {
+ char *ptr;
+ size_t len;
+ ipc_msg_hdr *hdr;
+ DNSServiceRef tmp;
+
+ len = sizeof(DNSServiceFlags);
+ len += sizeof(uint32_t);
+ len += strlen(fullname) + 1;
+ len += 3 * sizeof(uint16_t);
+ len += rdlen;
+ tmp = connect_to_server();
+ if (!tmp) return(kDNSServiceErr_Unknown);
+ hdr = create_hdr(reconfirm_record_request, &len, &ptr, 1);
+ if (!hdr) return(kDNSServiceErr_Unknown);
+
+ put_flags(flags, &ptr);
+ put_long(interfaceIndex, &ptr);
+ put_string(fullname, &ptr);
+ put_short(rrtype, &ptr);
+ put_short(rrclass, &ptr);
+ put_short(rdlen, &ptr);
+ put_rdata(rdlen, rdata, &ptr);
+ ConvertHeaderBytes(hdr);
+ write_all(tmp->sockfd, (char *)hdr, (int) len);
+ free(hdr);
+ DNSServiceRefDeallocate(tmp);
+ return(kDNSServiceErr_NoError);
+ }
+
diff --git a/usr/src/lib/libdns_sd/common/dnssd_ipc.c b/usr/src/lib/libdns_sd/common/dnssd_ipc.c
new file mode 100644
index 0000000000..92e76bab0c
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/dnssd_ipc.c
@@ -0,0 +1,135 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+
+$Log: dnssd_ipc.c,v $
+Revision 1.16 2006/08/14 23:05:53 cheshire
+Added "tab-width" emacs header line
+
+Revision 1.15 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
+Revision 1.14 2004/10/06 02:22:20 cheshire
+Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
+
+Revision 1.13 2004/10/01 22:15:55 rpantos
+rdar://problem/3824265: Replace APSL in client lib with BSD license.
+
+Revision 1.12 2004/09/16 23:14:24 cheshire
+Changes for Windows compatibility
+
+Revision 1.11 2004/06/18 04:56:09 rpantos
+casting goodness
+
+Revision 1.10 2004/06/12 01:08:14 cheshire
+Changes for Windows compatibility
+
+Revision 1.9 2004/05/18 23:51:27 cheshire
+Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
+
+Revision 1.8 2003/11/05 22:44:57 ksekar
+<rdar://problem/3335230>: No bounds checking when reading data from client
+Reviewed by: Stuart Cheshire
+
+Revision 1.7 2003/08/12 19:56:25 cheshire
+Update to APSL 2.0
+
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "dnssd_ipc.h"
+
+void put_long(const uint32_t l, char **ptr)
+ {
+ (*ptr)[0] = (char)((l >> 24) & 0xFF);
+ (*ptr)[1] = (char)((l >> 16) & 0xFF);
+ (*ptr)[2] = (char)((l >> 8) & 0xFF);
+ (*ptr)[3] = (char)((l ) & 0xFF);
+ *ptr += sizeof(uint32_t);
+ }
+
+uint32_t get_long(char **ptr)
+ {
+ uint8_t *p = (uint8_t*) *ptr;
+ *ptr += sizeof(uint32_t);
+ return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3]));
+ }
+
+void put_short(uint16_t s, char **ptr)
+ {
+ (*ptr)[0] = (char)((s >> 8) & 0xFF);
+ (*ptr)[1] = (char)((s ) & 0xFF);
+ *ptr += sizeof(uint16_t);
+ }
+
+uint16_t get_short(char **ptr)
+ {
+ uint8_t *p = (uint8_t*) *ptr;
+ *ptr += sizeof(uint16_t);
+ return((uint16_t) ((uint16_t)p[0] << 8 | p[1]));
+ }
+
+int put_string(const char *str, char **ptr)
+ {
+ if (!str) str = "";
+ strcpy(*ptr, str);
+ *ptr += strlen(str) + 1;
+ return 0;
+ }
+
+int get_string(char **ptr, char *buffer, int buflen)
+ {
+ int overrun = (int)strlen(*ptr) < buflen ? 0 : -1;
+ strncpy(buffer, *ptr, buflen - 1);
+ buffer[buflen - 1] = '\0';
+ *ptr += strlen(buffer) + 1;
+ return overrun;
+ }
+
+void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr)
+ {
+ memcpy(*ptr, rdata, rdlen);
+ *ptr += rdlen;
+ }
+
+char *get_rdata(char **ptr, int rdlen)
+ {
+ char *rd = *ptr;
+ *ptr += rdlen;
+ return rd;
+ }
+
+void ConvertHeaderBytes(ipc_msg_hdr *hdr)
+ {
+ hdr->version = htonl(hdr->version);
+ hdr->datalen = htonl(hdr->datalen);
+ hdr->flags = htonl(hdr->flags);
+ hdr->op = htonl(hdr->op );
+ hdr->reg_index = htonl(hdr->reg_index);
+ }
diff --git a/usr/src/lib/libdns_sd/common/dnssd_ipc.h b/usr/src/lib/libdns_sd/common/dnssd_ipc.h
new file mode 100644
index 0000000000..2f76591f9a
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/dnssd_ipc.h
@@ -0,0 +1,253 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Change History (most recent first):
+
+$Log: dnssd_ipc.h,v $
+Revision 1.23 2006/08/14 23:05:53 cheshire
+Added "tab-width" emacs header line
+
+Revision 1.22 2006/06/28 08:56:26 cheshire
+Added "_op" to the end of the operation code enum values,
+to differentiate them from the routines with the same names
+
+Revision 1.21 2005/09/29 06:38:13 herscher
+Remove #define MSG_WAITALL on Windows. We don't use this macro anymore, and it's presence causes warnings to be emitted when compiling against the latest Microsoft Platform SDK.
+
+Revision 1.20 2005/03/21 00:39:31 shersche
+<rdar://problem/4021486> Fix build warnings on Win32 platform
+
+Revision 1.19 2005/02/02 02:25:22 cheshire
+<rdar://problem/3980388> /var/run/mDNSResponder should be /var/run/mdnsd on Linux
+
+Revision 1.18 2005/01/27 22:57:56 cheshire
+Fix compile errors on gcc4
+
+Revision 1.17 2004/11/23 03:39:47 cheshire
+Let interface name/index mapping capability live directly in JNISupport.c,
+instead of having to call through to the daemon via IPC to get this information.
+
+Revision 1.16 2004/11/12 03:21:41 rpantos
+rdar://problem/3809541 Add DNSSDMapIfIndexToName, DNSSDMapNameToIfIndex.
+
+Revision 1.15 2004/10/06 02:22:20 cheshire
+Changed MacRoman copyright symbol (should have been UTF-8 in any case :-) to ASCII-compatible "(c)"
+
+Revision 1.14 2004/10/01 22:15:55 rpantos
+rdar://problem/3824265: Replace APSL in client lib with BSD license.
+
+Revision 1.13 2004/09/16 23:14:25 cheshire
+Changes for Windows compatibility
+
+Revision 1.12 2004/09/16 21:46:38 ksekar
+<rdar://problem/3665304> Need SPI for LoginWindow to associate a UID with a Wide Area domain
+
+Revision 1.11 2004/08/10 06:24:56 cheshire
+Use types with precisely defined sizes for 'op' and 'reg_index', for better
+compatibility if the daemon and the client stub are built using different compilers
+
+Revision 1.10 2004/07/07 17:39:25 shersche
+Change MDNS_SERVERPORT from 5533 to 5354.
+
+Revision 1.9 2004/06/25 00:26:27 rpantos
+Changes to fix the Posix build on Solaris.
+
+Revision 1.8 2004/06/18 04:56:51 rpantos
+Add layer for platform code
+
+Revision 1.7 2004/06/12 01:08:14 cheshire
+Changes for Windows compatibility
+
+Revision 1.6 2003/08/12 19:56:25 cheshire
+Update to APSL 2.0
+
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifndef DNSSD_IPC_H
+#define DNSSD_IPC_H
+
+#include "dns_sd.h"
+
+
+//
+// Common cross platform services
+//
+#if defined(WIN32)
+# include <winsock2.h>
+# define dnssd_InvalidSocket INVALID_SOCKET
+# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK
+# define dnssd_EINTR WSAEINTR
+# define dnssd_sock_t SOCKET
+# define dnssd_socklen_t int
+# define dnssd_sockbuf_t const char*
+# define dnssd_close(sock) closesocket(sock)
+# define dnssd_errno() WSAGetLastError()
+# define ssize_t int
+# define getpid _getpid
+#else
+# include <sys/types.h>
+# include <unistd.h>
+# include <sys/un.h>
+# include <string.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/stat.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# define dnssd_InvalidSocket -1
+# define dnssd_EWOULDBLOCK EWOULDBLOCK
+# define dnssd_EINTR EINTR
+# define dnssd_EPIPE EPIPE
+# define dnssd_sock_t int
+# define dnssd_socklen_t unsigned int
+# define dnssd_sockbuf_t const char*
+# define dnssd_close(sock) close(sock)
+# define dnssd_errno() errno
+#endif
+
+#if defined(USE_TCP_LOOPBACK)
+# define AF_DNSSD AF_INET
+# define MDNS_TCP_SERVERADDR "127.0.0.1"
+# define MDNS_TCP_SERVERPORT 5354
+# define LISTENQ 5
+# define dnssd_sockaddr_t struct sockaddr_in
+#else
+# define AF_DNSSD AF_LOCAL
+# ifndef MDNS_UDS_SERVERPATH
+# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder"
+# endif
+# define LISTENQ 100
+ // longest legal control path length
+# define MAX_CTLPATH 256
+# define dnssd_sockaddr_t struct sockaddr_un
+#endif
+
+
+//#define UDSDEBUG // verbose debug output
+
+// Compatibility workaround
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif
+
+// General UDS constants
+#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record
+
+// IPC data encoding constants and types
+#define VERSION 1
+#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
+#define IPC_FLAGS_REUSE_SOCKET 2 // set flag if synchronous errors are to be sent via the primary socket
+ // (if not set, first string in message buffer must be path to error socket
+
+typedef enum
+ {
+ connection = 1, // connected socket via DNSServiceConnect()
+ reg_record_request, // reg/remove record only valid for connected sockets
+ remove_record_request,
+ enumeration_request,
+ reg_service_request,
+ browse_request,
+ resolve_request,
+ query_request,
+ reconfirm_record_request,
+ add_record_request,
+ update_record_request,
+ setdomain_request
+ } request_op_t;
+
+typedef enum
+ {
+ enumeration_reply_op = 64,
+ reg_service_reply_op,
+ browse_reply_op,
+ resolve_reply_op,
+ query_reply_op,
+ reg_record_reply_op
+ } reply_op_t;
+
+typedef struct ipc_msg_hdr_struct ipc_msg_hdr;
+
+// client stub callback to process message from server and deliver results to
+// client application
+
+typedef void (*process_reply_callback)
+ (
+ DNSServiceRef sdr,
+ ipc_msg_hdr *hdr,
+ char *msg
+ );
+
+// allow 64-bit client to interoperate w/ 32-bit daemon
+typedef union
+ {
+ void *context;
+ uint32_t ptr64[2];
+ } client_context_t;
+
+typedef struct ipc_msg_hdr_struct
+ {
+ uint32_t version;
+ uint32_t datalen;
+ uint32_t flags;
+ uint32_t op; // request_op_t or reply_op_t
+ client_context_t client_context; // context passed from client, returned by server in corresponding reply
+ uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a
+ // socket connected by DNSServiceConnect(). Must be unique in the scope of the connection, such that and
+ // index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord())
+ uint32_t padbytes;
+ } ipc_msg_hdr_struct;
+
+// it is advanced to point to the next field, or the end of the message
+// routines to write to and extract data from message buffers.
+// caller responsible for bounds checking.
+// ptr is the address of the pointer to the start of the field.
+// it is advanced to point to the next field, or the end of the message
+
+void put_long(const uint32_t l, char **ptr);
+uint32_t get_long(char **ptr);
+
+void put_short(uint16_t s, char **ptr);
+uint16_t get_short(char **ptr);
+
+#define put_flags put_long
+#define get_flags get_long
+
+#define put_error_code put_long
+#define get_error_code get_long
+
+int put_string(const char *str, char **ptr);
+int get_string(char **ptr, char *buffer, int buflen);
+
+void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
+char *get_rdata(char **ptr, int rdlen); // return value is rdata pointed to by *ptr -
+ // rdata is not copied from buffer.
+
+void ConvertHeaderBytes(ipc_msg_hdr *hdr);
+
+#endif // DNSSD_IPC_H
diff --git a/usr/src/lib/libdns_sd/common/llib-ldns_sd b/usr/src/lib/libdns_sd/common/llib-ldns_sd
new file mode 100644
index 0000000000..464e3b9a6d
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/llib-ldns_sd
@@ -0,0 +1,32 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <dns_sd.h>
diff --git a/usr/src/lib/libdns_sd/common/mapfile-vers b/usr/src/lib/libdns_sd/common/mapfile-vers
new file mode 100644
index 0000000000..012b730ca1
--- /dev/null
+++ b/usr/src/lib/libdns_sd/common/mapfile-vers
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUNW_1.1 {
+ global:
+ DNSServiceAddRecord;
+ DNSServiceBrowse;
+ DNSServiceConstructFullName;
+ DNSServiceCreateConnection;
+ DNSServiceEnumerateDomains;
+ DNSServiceProcessResult;
+ DNSServiceQueryRecord;
+ DNSServiceReconfirmRecord;
+ DNSServiceRefDeallocate;
+ DNSServiceRefSockFD;
+ DNSServiceRegister;
+ DNSServiceRegisterRecord;
+ DNSServiceRemoveRecord;
+ DNSServiceResolve;
+ DNSServiceUpdateRecord;
+ TXTRecordContainsKey;
+ TXTRecordCreate;
+ TXTRecordDeallocate;
+ TXTRecordGetBytesPtr;
+ TXTRecordGetCount;
+ TXTRecordGetItemAtIndex;
+ TXTRecordGetLength;
+ TXTRecordGetValuePtr;
+ TXTRecordRemoveValue;
+ TXTRecordSetValue;
+ local:
+ *;
+};
diff --git a/usr/src/lib/libdns_sd/i386/Makefile b/usr/src/lib/libdns_sd/i386/Makefile
new file mode 100644
index 0000000000..9c1be5bf3a
--- /dev/null
+++ b/usr/src/lib/libdns_sd/i386/Makefile
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libdns_sd/java/Makefile b/usr/src/lib/libdns_sd/java/Makefile
new file mode 100644
index 0000000000..5b015fc86e
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/Makefile
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include $(SRC)/lib/Makefile.lib
+
+POFILE = libjdns_sd.po
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all install clean clobber lint: com/apple .WAIT $(SUBDIRS)
+
+com/apple $(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/libdns_sd/java/Makefile.com b/usr/src/lib/libdns_sd/java/Makefile.com
new file mode 100644
index 0000000000..f66463ac2f
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/Makefile.com
@@ -0,0 +1,57 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+LIBRARY= libjdns_sd.a
+VERS= .1
+
+OBJECTS= JNISupport.o
+
+include $(SRC)/lib/Makefile.lib
+
+LIBS = $(DYNLIB)
+
+SRCDIR = ../common
+
+C99MODE = $(C99_ENABLE)
+CPPFLAGS += -I$(JAVA_ROOT)/include -I$(JAVA_ROOT)/include/solaris
+CPPFLAGS += -I../com/apple/dnssd
+CPPFLAGS += -D_REENTRANT
+
+LDLIBS += -lc -lsocket -ldns_sd
+
+CLEANFILES= $(LINTOUT) $(LINTLIB)
+
+LINTLIB =
+
+.KEEP_STATE:
+
+lint: lintcheck
+
+include $(SRC)/lib/Makefile.targ
+
+pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libdns_sd/java/amd64/Makefile b/usr/src/lib/libdns_sd/java/amd64/Makefile
new file mode 100644
index 0000000000..b645e1caed
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/amd64/Makefile
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libdns_sd/java/com/apple/Makefile b/usr/src/lib/libdns_sd/java/com/apple/Makefile
new file mode 100644
index 0000000000..8cfdc2e941
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/Makefile
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include Makefile.com
+
+SUBDIRS = dnssd
+
+all:= TARGET = all
+clean:= TARGET = clean
+clobber:= TARGET = clobber
+install:= TARGET = install
+
+.KEEP_STATE:
+
+all clean install clobber: ${SUBDIRS}
+
+${SUBDIRS}: FRC
+ cd $@; pwd; $(MAKE) $(TARGET)
+
+lint:
+
+.WAIT:
+
+FRC:
diff --git a/usr/src/lib/libdns_sd/java/com/apple/Makefile.com b/usr/src/lib/libdns_sd/java/com/apple/Makefile.com
new file mode 100644
index 0000000000..e699ff14a4
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/Makefile.com
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include $(SRC)/lib/Makefile.lib
+
+ROOTDNSSDJAVAHOME = $(ROOT)/usr/share/lib/java
+
+.KEEP_STATE:
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java
new file mode 100644
index 0000000000..689cb8ba57
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java
@@ -0,0 +1,51 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: BaseListener.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/** A base class for DNSSD listeners. */
+
+public interface BaseListener
+{
+ /** Called to report DNSSD operation failures.<P>
+
+ @param service
+ The service that encountered the failure.
+ <P>
+ @param errorCode
+ Indicates the failure that occurred. See {@link DNSSDException} for error codes.
+ */
+ void operationFailed( DNSSDService service, int errorCode);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java
new file mode 100644
index 0000000000..0ae9b938ba
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java
@@ -0,0 +1,88 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: BrowseListener.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/** A listener that receives results from {@link DNSSD#browse}. */
+
+public interface BrowseListener extends BaseListener
+{
+ /** Called to report discovered services.<P>
+
+ @param browser
+ The active browse service.
+ <P>
+ @param flags
+ Possible values are DNSSD.MORE_COMING.
+ <P>
+ @param ifIndex
+ The interface on which the service is advertised. This index should be passed
+ to {@link DNSSD#resolve} when resolving the service.
+ <P>
+ @param serviceName
+ The service name discovered.
+ <P>
+ @param regType
+ The registration type, as passed in to DNSSD.browse().
+ <P>
+ @param domain
+ The domain in which the service was discovered.
+ */
+ void serviceFound( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain);
+
+ /** Called to report services which have been deregistered.<P>
+
+ @param browser
+ The active browse service.
+ <P>
+ @param flags
+ Possible values are DNSSD.MORE_COMING.
+ <P>
+ @param ifIndex
+ The interface on which the service is advertised.
+ <P>
+ @param serviceName
+ The service name which has deregistered.
+ <P>
+ @param regType
+ The registration type, as passed in to DNSSD.browse().
+ <P>
+ @param domain
+ The domain in which the service was discovered.
+ */
+ void serviceLost( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java
new file mode 100644
index 0000000000..6caf3a7791
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java
@@ -0,0 +1,68 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: DNSRecord.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/12/11 03:00:59 rpantos
+<rdar://problem/3907498> Java DNSRecord API should be cleaned up
+
+Revision 1.1 2004/04/30 16:32:34 rpantos
+First checked in.
+
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/**
+ Reference to a record returned by {@link DNSSDRegistration#addRecord}.<P>
+
+ Note: client is responsible for serializing access to these objects if
+ they are shared between concurrent threads.
+*/
+
+public interface DNSRecord
+{
+ /** Update a registered resource record.<P>
+ The record must either be the primary txt record of a service registered via DNSSD.register(),
+ or a record added to a registered service via addRecord().<P>
+
+ @param flags
+ Currently unused, reserved for future use.
+ <P>
+ @param rData
+ The new rdata to be contained in the updated resource record.
+ <P>
+ @param ttl
+ The time to live of the updated resource record, in seconds.
+ */
+ void update( int flags, byte[] rData, int ttl)
+ throws DNSSDException;
+
+ /** Remove a registered resource record.<P>
+ */
+ void remove()
+ throws DNSSDException;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java
new file mode 100644
index 0000000000..9841c9492b
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java
@@ -0,0 +1,897 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: DNSSD.java,v $
+Revision 1.11 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.10 2006/06/20 23:05:55 rpantos
+<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
+
+Revision 1.9 2005/10/26 01:52:24 cheshire
+<rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
+
+Revision 1.8 2005/07/11 01:55:21 cheshire
+<rdar://problem/4175511> Race condition in Java API
+
+Revision 1.7 2005/07/05 13:01:52 cheshire
+<rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
+
+Revision 1.6 2005/07/05 00:02:25 cheshire
+Add missing comma
+
+Revision 1.5 2005/07/04 21:13:47 cheshire
+Add missing error message strings
+
+Revision 1.4 2004/12/11 03:00:59 rpantos
+<rdar://problem/3907498> Java DNSRecord API should be cleaned up
+
+Revision 1.3 2004/11/12 03:23:08 rpantos
+rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
+
+Revision 1.2 2004/05/20 17:43:18 cheshire
+Fix invalid UTF-8 characters in file
+
+Revision 1.1 2004/04/30 16:32:34 rpantos
+First checked in.
+
+
+ This file declares and implements DNSSD, the central Java factory class
+ for doing DNS Service Discovery. It includes the mostly-abstract public
+ interface, as well as the Apple* implementation subclasses.
+ */
+
+/*
+ * ident "%Z%%M% %I% %E% SMI"
+ */
+
+package com.apple.dnssd;
+
+
+/**
+ DNSSD provides access to DNS Service Discovery features of ZeroConf networking.<P>
+
+ It is a factory class that is used to invoke registration and discovery-related
+ operations. Most operations are non-blocking; clients are called back through an interface
+ with the result of an operation. Callbacks are made from a separate worker thread.<P>
+
+ For example, in this program<P>
+ <PRE><CODE>
+ class MyClient implements BrowseListener {
+ void lookForWebServers() {
+ myBrowser = DNSSD.browse("_http_.tcp", this);
+ }
+
+ public void serviceFound(DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain) {}
+ ...
+ }</CODE></PRE>
+ <CODE>MyClient.serviceFound()</CODE> would be called for every HTTP server discovered in the
+ default browse domain(s).
+*/
+
+abstract public class DNSSD
+{
+ /** Flag indicates to a {@link BrowseListener} that another result is
+ queued. Applications should not update their UI to display browse
+ results if the MORE_COMING flag is set; they will be called at least once
+ more with the flag clear.
+ */
+ public static final int MORE_COMING = ( 1 << 0 );
+
+ /** If flag is set in a {@link DomainListener} callback, indicates that the result is the default domain. */
+ public static final int DEFAULT = ( 1 << 2 );
+
+ /** If flag is set, a name conflict will trigger an exception when registering non-shared records.<P>
+ A name must be explicitly specified when registering a service if this bit is set
+ (i.e. the default name may not not be used).
+ */
+ public static final int NO_AUTO_RENAME = ( 1 << 3 );
+
+ /** If flag is set, allow multiple records with this name on the network (e.g. PTR records)
+ when registering individual records on a {@link DNSSDRegistration}.
+ */
+ public static final int SHARED = ( 1 << 4 );
+
+ /** If flag is set, records with this name must be unique on the network (e.g. SRV records). */
+ public static final int UNIQUE = ( 1 << 5 );
+
+ /** Set flag when calling enumerateDomains() to restrict results to domains recommended for browsing. */
+ public static final int BROWSE_DOMAINS = ( 1 << 6 );
+ /** Set flag when calling enumerateDomains() to restrict results to domains recommended for registration. */
+ public static final int REGISTRATION_DOMAINS = ( 1 << 7 );
+
+ /** Maximum length, in bytes, of a domain name represented as an escaped C-String. */
+ public static final int MAX_DOMAIN_NAME = 1005;
+
+ /** Pass for ifIndex to specify all available interfaces. */
+ public static final int ALL_INTERFACES = 0;
+
+ /** Pass for ifIndex to specify the localhost interface. */
+ public static final int LOCALHOST_ONLY = -1;
+
+ /** Browse for instances of a service.<P>
+
+ Note: browsing consumes network bandwidth. Call {@link DNSSDService#stop} when you have finished browsing.<P>
+
+ @param flags
+ Currently ignored, reserved for future use.
+ <P>
+ @param ifIndex
+ If non-zero, specifies the interface on which to browse for services
+ (the index for a given interface is determined via the if_nametoindex()
+ family of calls.) Most applications will pass 0 to browse on all available
+ interfaces. Pass -1 to only browse for services provided on the local host.
+ <P>
+ @param regType
+ The registration type being browsed for followed by the protocol, separated by a
+ dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ <P>
+ @param domain
+ If non-null, specifies the domain on which to browse for services.
+ Most applications will not specify a domain, instead browsing on the
+ default domain(s).
+ <P>
+ @param listener
+ This object will get called when instances of the service are discovered (or disappear).
+ <P>
+ @return A {@link DNSSDService} that represents the active browse operation.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDService browse( int flags, int ifIndex, String regType, String domain, BrowseListener listener)
+ throws DNSSDException
+ { return getInstance()._makeBrowser( flags, ifIndex, regType, domain, listener); }
+
+ /** Browse for instances of a service. Use default flags, ifIndex and domain.<P>
+
+ @param regType
+ The registration type being browsed for followed by the protocol, separated by a
+ dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ <P>
+ @param listener
+ This object will get called when instances of the service are discovered (or disappear).
+ <P>
+ @return A {@link DNSSDService} that represents the active browse operation.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDService browse( String regType, BrowseListener listener)
+ throws DNSSDException
+ { return browse( 0, 0, regType, "", listener); }
+
+ /** Resolve a service name discovered via browse() to a target host name, port number, and txt record.<P>
+
+ Note: Applications should NOT use resolve() solely for txt record monitoring - use
+ queryRecord() instead, as it is more efficient for this task.<P>
+
+ Note: When the desired results have been returned, the client MUST terminate the resolve by
+ calling {@link DNSSDService#stop}.<P>
+
+ Note: resolve() behaves correctly for typical services that have a single SRV record and
+ a single TXT record (the TXT record may be empty.) To resolve non-standard services with
+ multiple SRV or TXT records, use queryRecord().<P>
+
+ @param flags
+ Currently ignored, reserved for future use.
+ <P>
+ @param ifIndex
+ The interface on which to resolve the service. The client should
+ pass the interface on which the serviceName was discovered (i.e.
+ the ifIndex passed to the serviceFound() callback)
+ or 0 to resolve the named service on all available interfaces.
+ <P>
+ @param serviceName
+ The servicename to be resolved.
+ <P>
+ @param regType
+ The registration type being resolved followed by the protocol, separated by a
+ dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ <P>
+ @param domain
+ The domain on which the service is registered, i.e. the domain passed
+ to the serviceFound() callback.
+ <P>
+ @param listener
+ This object will get called when the service is resolved.
+ <P>
+ @return A {@link DNSSDService} that represents the active resolve operation.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDService resolve( int flags, int ifIndex, String serviceName, String regType,
+ String domain, ResolveListener listener)
+ throws DNSSDException
+ { return getInstance()._resolve( flags, ifIndex, serviceName, regType, domain, listener); }
+
+ /** Register a service, to be discovered via browse() and resolve() calls.<P>
+ @param flags
+ Possible values are: NO_AUTO_RENAME.
+ <P>
+ @param ifIndex
+ If non-zero, specifies the interface on which to register the service
+ (the index for a given interface is determined via the if_nametoindex()
+ family of calls.) Most applications will pass 0 to register on all
+ available interfaces. Pass -1 to register a service only on the local
+ machine (service will not be visible to remote hosts).
+ <P>
+ @param serviceName
+ If non-null, specifies the service name to be registered.
+ Applications need not specify a name, in which case the
+ computer name is used (this name is communicated to the client via
+ the serviceRegistered() callback).
+ <P>
+ @param regType
+ The registration type being registered followed by the protocol, separated by a
+ dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ <P>
+ @param domain
+ If non-null, specifies the domain on which to advertise the service.
+ Most applications will not specify a domain, instead automatically
+ registering in the default domain(s).
+ <P>
+ @param host
+ If non-null, specifies the SRV target host name. Most applications
+ will not specify a host, instead automatically using the machine's
+ default host name(s). Note that specifying a non-null host does NOT
+ create an address record for that host - the application is responsible
+ for ensuring that the appropriate address record exists, or creating it
+ via {@link DNSSDRegistration#addRecord}.
+ <P>
+ @param port
+ The port on which the service accepts connections. Pass 0 for a
+ "placeholder" service (i.e. a service that will not be discovered by
+ browsing, but will cause a name conflict if another client tries to
+ register that same name.) Most clients will not use placeholder services.
+ <P>
+ @param txtRecord
+ The txt record rdata. May be null. Note that a non-null txtRecord
+ MUST be a properly formatted DNS TXT record, i.e. &lt;length byte&gt; &lt;data&gt;
+ &lt;length byte&gt; &lt;data&gt; ...
+ <P>
+ @param listener
+ This object will get called when the service is registered.
+ <P>
+ @return A {@link DNSSDRegistration} that controls the active registration.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDRegistration register( int flags, int ifIndex, String serviceName, String regType,
+ String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener)
+ throws DNSSDException
+ { return getInstance()._register( flags, ifIndex, serviceName, regType, domain, host, port, txtRecord, listener); }
+
+ /** Register a service, to be discovered via browse() and resolve() calls. Use default flags, ifIndex, domain, host and txtRecord.<P>
+ @param serviceName
+ If non-null, specifies the service name to be registered.
+ Applications need not specify a name, in which case the
+ computer name is used (this name is communicated to the client via
+ the serviceRegistered() callback).
+ <P>
+ @param regType
+ The registration type being registered followed by the protocol, separated by a
+ dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ <P>
+ @param port
+ The port on which the service accepts connections. Pass 0 for a
+ "placeholder" service (i.e. a service that will not be discovered by
+ browsing, but will cause a name conflict if another client tries to
+ register that same name.) Most clients will not use placeholder services.
+ <P>
+ @param listener
+ This object will get called when the service is registered.
+ <P>
+ @return A {@link DNSSDRegistration} that controls the active registration.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDRegistration register( String serviceName, String regType, int port, RegisterListener listener)
+ throws DNSSDException
+ { return register( 0, 0, serviceName, regType, null, null, port, null, listener); }
+
+ /** Create a {@link DNSSDRecordRegistrar} allowing efficient registration of
+ multiple individual records.<P>
+ <P>
+ @return A {@link DNSSDRecordRegistrar} that can be used to register records.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDRecordRegistrar createRecordRegistrar( RegisterRecordListener listener)
+ throws DNSSDException
+ { return getInstance()._createRecordRegistrar( listener); }
+
+ /** Query for an arbitrary DNS record.<P>
+ @param flags
+ Possible values are: MORE_COMING.
+ <P>
+ @param ifIndex
+ If non-zero, specifies the interface on which to issue the query
+ (the index for a given interface is determined via the if_nametoindex()
+ family of calls.) Passing 0 causes the name to be queried for on all
+ interfaces. Passing -1 causes the name to be queried for only on the
+ local host.
+ <P>
+ @param serviceName
+ The full domain name of the resource record to be queried for.
+ <P>
+ @param rrtype
+ The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc)
+ as defined in nameser.h.
+ <P>
+ @param rrclass
+ The class of the resource record, as defined in nameser.h
+ (usually 1 for the Internet class).
+ <P>
+ @param listener
+ This object will get called when the query completes.
+ <P>
+ @return A {@link DNSSDService} that controls the active query.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDService queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
+ int rrclass, QueryListener listener)
+ throws DNSSDException
+ { return getInstance()._queryRecord( flags, ifIndex, serviceName, rrtype, rrclass, listener); }
+
+ /** Asynchronously enumerate domains available for browsing and registration.<P>
+
+ Currently, the only domain returned is "local.", but other domains will be returned in future.<P>
+
+ The enumeration MUST be cancelled by calling {@link DNSSDService#stop} when no more domains
+ are to be found.<P>
+ @param flags
+ Possible values are: BROWSE_DOMAINS, REGISTRATION_DOMAINS.
+ <P>
+ @param ifIndex
+ If non-zero, specifies the interface on which to look for domains.
+ (the index for a given interface is determined via the if_nametoindex()
+ family of calls.) Most applications will pass 0 to enumerate domains on
+ all interfaces.
+ <P>
+ @param listener
+ This object will get called when domains are found.
+ <P>
+ @return A {@link DNSSDService} that controls the active enumeration.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static DNSSDService enumerateDomains( int flags, int ifIndex, DomainListener listener)
+ throws DNSSDException
+ { return getInstance()._enumerateDomains( flags, ifIndex, listener); }
+
+ /** Concatenate a three-part domain name (as provided to the listeners) into a
+ properly-escaped full domain name. Note that strings passed to listeners are
+ ALREADY ESCAPED where necessary.<P>
+ @param serviceName
+ The service name - any dots or slashes must NOT be escaped.
+ May be null (to construct a PTR record name, e.g. "_ftp._tcp.apple.com").
+ <P>
+ @param regType
+ The registration type followed by the protocol, separated by a dot (e.g. "_ftp._tcp").
+ <P>
+ @param domain
+ The domain name, e.g. "apple.com". Any literal dots or backslashes must be escaped.
+ <P>
+ @return The full domain name.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static String constructFullName( String serviceName, String regType, String domain)
+ throws DNSSDException
+ { return getInstance()._constructFullName( serviceName, regType, domain); }
+
+ /** Instruct the daemon to verify the validity of a resource record that appears to
+ be out of date. (e.g. because tcp connection to a service's target failed.) <P>
+
+ Causes the record to be flushed from the daemon's cache (as well as all other
+ daemons' caches on the network) if the record is determined to be invalid.<P>
+ @param flags
+ Currently unused, reserved for future use.
+ <P>
+ @param ifIndex
+ If non-zero, specifies the interface on which to reconfirm the record
+ (the index for a given interface is determined via the if_nametoindex()
+ family of calls.) Passing 0 causes the name to be reconfirmed on all
+ interfaces. Passing -1 causes the name to be reconfirmed only on the
+ local host.
+ <P>
+ @param fullName
+ The resource record's full domain name.
+ <P>
+ @param rrtype
+ The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h.
+ <P>
+ @param rrclass
+ The class of the resource record, as defined in nameser.h (usually 1).
+ <P>
+ @param rdata
+ The raw rdata of the resource record.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static void reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
+ int rrclass, byte[] rdata)
+ { getInstance()._reconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata); }
+
+ /** Return the canonical name of a particular interface index.<P>
+ @param ifIndex
+ A valid interface index. Must not be ALL_INTERFACES.
+ <P>
+ @return The name of the interface, which should match java.net.NetworkInterface.getName().
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static String getNameForIfIndex( int ifIndex)
+ { return getInstance()._getNameForIfIndex( ifIndex); }
+
+ /** Return the index of a named interface.<P>
+ @param ifName
+ A valid interface name. An example is java.net.NetworkInterface.getName().
+ <P>
+ @return The interface index.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public static int getIfIndexForName( String ifName)
+ { return getInstance()._getIfIndexForName( ifName); }
+
+ protected DNSSD() {} // prevent direct instantiation
+
+ /** Return the single instance of DNSSD. */
+ static protected final DNSSD getInstance()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if ( sm != null)
+ sm.checkPermission( new RuntimePermission( "getDNSSDInstance"));
+ return fInstance;
+ }
+
+ abstract protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener listener)
+ throws DNSSDException;
+
+ abstract protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType,
+ String domain, ResolveListener listener)
+ throws DNSSDException;
+
+ abstract protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType,
+ String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener)
+ throws DNSSDException;
+
+ abstract protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener)
+ throws DNSSDException;
+
+ abstract protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
+ int rrclass, QueryListener listener)
+ throws DNSSDException;
+
+ abstract protected DNSSDService _enumerateDomains( int flags, int ifIndex, DomainListener listener)
+ throws DNSSDException;
+
+ abstract protected String _constructFullName( String serviceName, String regType, String domain)
+ throws DNSSDException;
+
+ abstract protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
+ int rrclass, byte[] rdata);
+
+ abstract protected String _getNameForIfIndex( int ifIndex);
+
+ abstract protected int _getIfIndexForName( String ifName);
+
+ protected static DNSSD fInstance;
+
+ static
+ {
+ try
+ {
+ String name = System.getProperty( "com.apple.dnssd.DNSSD" );
+ if( name == null )
+ name = "com.apple.dnssd.AppleDNSSD"; // Fall back to Apple-provided class.
+ fInstance = (DNSSD) Class.forName( name ).newInstance();
+ }
+ catch( Exception e )
+ {
+ throw new InternalError( "cannot instantiate DNSSD" + e );
+ }
+ }
+}
+
+
+// Concrete implementation of DNSSDException
+class AppleDNSSDException extends DNSSDException
+{
+ public AppleDNSSDException( int errorCode) { fErrorCode = errorCode; }
+
+ public int getErrorCode() { return fErrorCode; }
+
+ public String getMessage()
+ {
+ final String kMessages[] = { // should probably be put into a resource or something
+ "UNKNOWN",
+ "NO_SUCH_NAME",
+ "NO_MEMORY",
+ "BAD_PARAM",
+ "BAD_REFERENCE",
+ "BAD_STATE",
+ "BAD_FLAGS",
+ "UNSUPPORTED",
+ "NOT_INITIALIZED",
+ "NO_CACHE",
+ "ALREADY_REGISTERED",
+ "NAME_CONFLICT",
+ "INVALID",
+ "FIREWALL",
+ "INCOMPATIBLE",
+ "BAD_INTERFACE_INDEX",
+ "REFUSED",
+ "NOSUCHRECORD",
+ "NOAUTH",
+ "NOSUCHKEY",
+ "NATTRAVERSAL",
+ "DOUBLENAT",
+ "BADTIME",
+ "BADSIG",
+ "BADKEY",
+ "TRANSIENT"
+ };
+
+ if ( fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length))
+ {
+ return "DNS-SD Error " + String.valueOf( fErrorCode) + ": " + kMessages[ UNKNOWN - fErrorCode];
+ }
+ else
+ return super.getMessage() + "(" + String.valueOf( fErrorCode) + ")";
+ }
+
+ protected int fErrorCode;
+}
+
+// The concrete, default implementation.
+class AppleDNSSD extends DNSSD
+{
+ static
+ {
+ System.loadLibrary( "jdns_sd");
+
+ int libInitResult = InitLibrary( 1);
+
+ if ( libInitResult != DNSSDException.NO_ERROR)
+ throw new InternalError( "cannot instantiate DNSSD: " + new AppleDNSSDException( libInitResult).getMessage());
+ }
+
+ static public boolean hasAutoCallbacks; // Set by InitLibrary() to value of AUTO_CALLBACKS
+
+ protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client)
+ throws DNSSDException
+ {
+ return new AppleBrowser( flags, ifIndex, regType, domain, client);
+ }
+
+ protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType,
+ String domain, ResolveListener client)
+ throws DNSSDException
+ {
+ return new AppleResolver( flags, ifIndex, serviceName, regType, domain, client);
+ }
+
+ protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType,
+ String domain, String host, int port, TXTRecord txtRecord, RegisterListener client)
+ throws DNSSDException
+ {
+ return new AppleRegistration( flags, ifIndex, serviceName, regType, domain, host, port,
+ ( txtRecord != null) ? txtRecord.getRawBytes() : null, client);
+ }
+
+ protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener)
+ throws DNSSDException
+ {
+ return new AppleRecordRegistrar( listener);
+ }
+
+ protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype,
+ int rrclass, QueryListener client)
+ throws DNSSDException
+ {
+ return new AppleQuery( flags, ifIndex, serviceName, rrtype, rrclass, client);
+ }
+
+ protected DNSSDService _enumerateDomains( int flags, int ifIndex, DomainListener listener)
+ throws DNSSDException
+ {
+ return new AppleDomainEnum( flags, ifIndex, listener);
+ }
+
+ protected String _constructFullName( String serviceName, String regType, String domain)
+ throws DNSSDException
+ {
+ String[] responseHolder = new String[1]; // lame maneuver to get around Java's lack of reference parameters
+
+ int rc = ConstructName( serviceName, regType, domain, responseHolder);
+ if ( rc != 0)
+ throw new AppleDNSSDException( rc);
+
+ return responseHolder[0];
+ }
+
+ protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
+ int rrclass, byte[] rdata)
+ {
+ ReconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata);
+ }
+
+ protected String _getNameForIfIndex( int ifIndex)
+ {
+ return GetNameForIfIndex( ifIndex);
+ }
+
+ protected int _getIfIndexForName( String ifName)
+ {
+ return GetIfIndexForName( ifName);
+ }
+
+
+ protected native int ConstructName( String serviceName, String regType, String domain, String[] pOut);
+
+ protected native void ReconfirmRecord( int flags, int ifIndex, String fullName, int rrtype,
+ int rrclass, byte[] rdata);
+
+ protected native String GetNameForIfIndex( int ifIndex);
+
+ protected native int GetIfIndexForName( String ifName);
+
+ protected static native int InitLibrary( int callerVersion);
+}
+
+class AppleService implements DNSSDService, Runnable
+{
+ public AppleService(BaseListener listener) { fNativeContext = 0; fListener = listener; }
+
+ public void stop() { this.HaltOperation(); }
+
+ /* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
+ protected native int BlockForData();
+
+ /* Call ProcessResults when data appears on socket descriptor. */
+ protected native int ProcessResults();
+
+ protected synchronized native void HaltOperation();
+
+ protected void ThrowOnErr( int rc) throws DNSSDException
+ {
+ if ( rc != 0)
+ throw new AppleDNSSDException( rc);
+ }
+
+ protected long /* warning */ fNativeContext; // Private storage for native side
+
+ public void run()
+ {
+ while ( true )
+ {
+ // Note: We want to allow our DNS-SD operation to be stopped from other threads, so we have to
+ // block waiting for data *outside* the synchronized section. Because we're doing this unsynchronized
+ // we have to write some careful code. Suppose our DNS-SD operation is stopped from some other thread,
+ // and then immediately afterwards that thread (or some third, unrelated thread) starts a new DNS-SD
+ // operation. The Unix kernel always allocates the lowest available file descriptor to a new socket,
+ // so the same file descriptor is highly likely to be reused for the new operation, and if our old
+ // stale ServiceThread accidentally consumes bytes off that new socket we'll get really messed up.
+ // To guard against that, before calling ProcessResults we check to ensure that our
+ // fNativeContext has not been deleted, which is a telltale sign that our operation was stopped.
+ // After calling ProcessResults we check again, because it's extremely common for callback
+ // functions to stop their own operation and start others. For example, a resolveListener callback
+ // may well stop the resolve and then start a QueryRecord call to monitor the TXT record.
+ //
+ // The remaining risk is that between our checking fNativeContext and calling ProcessResults(),
+ // some other thread could stop the operation and start a new one using same file descriptor, and
+ // we wouldn't know. To prevent this, the AppleService object's HaltOperation() routine is declared
+ // synchronized and we perform our checks synchronized on the AppleService object, which ensures
+ // that HaltOperation() can't execute while we're doing it. Because Java locks are re-entrant this
+ // locking DOESN'T prevent the callback routine from stopping its own operation, but DOES prevent
+ // any other thread from stopping it until after the callback has completed and returned to us here.
+
+ int result = BlockForData();
+ synchronized (this)
+ {
+ if (fNativeContext == 0) break; // Some other thread stopped our DNSSD operation; time to terminate this thread
+ if (result == 0) continue; // If BlockForData() said there was no data, go back and block again
+ result = ProcessResults();
+ if (fNativeContext == 0) break; // Event listener stopped its own DNSSD operation; terminate this thread
+ if (result != 0) { fListener.operationFailed(this, result); break; } // If error, notify listener
+ }
+ }
+ }
+
+ protected BaseListener fListener;
+}
+
+
+class AppleBrowser extends AppleService
+{
+ public AppleBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client)
+ throws DNSSDException
+ {
+ super(client);
+ this.ThrowOnErr( this.CreateBrowser( flags, ifIndex, regType, domain));
+ if ( !AppleDNSSD.hasAutoCallbacks)
+ new Thread(this).start();
+ }
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int CreateBrowser( int flags, int ifIndex, String regType, String domain);
+}
+
+class AppleResolver extends AppleService
+{
+ public AppleResolver( int flags, int ifIndex, String serviceName, String regType,
+ String domain, ResolveListener client)
+ throws DNSSDException
+ {
+ super(client);
+ this.ThrowOnErr( this.CreateResolver( flags, ifIndex, serviceName, regType, domain));
+ if ( !AppleDNSSD.hasAutoCallbacks)
+ new Thread(this).start();
+ }
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int CreateResolver( int flags, int ifIndex, String serviceName, String regType,
+ String domain);
+}
+
+// An AppleDNSRecord is a simple wrapper around a dns_sd DNSRecord.
+class AppleDNSRecord implements DNSRecord
+{
+ public AppleDNSRecord( AppleService owner)
+ {
+ fOwner = owner;
+ fRecord = 0; // record always starts out empty
+ }
+
+ public void update( int flags, byte[] rData, int ttl)
+ throws DNSSDException
+ {
+ this.ThrowOnErr( this.Update( flags, rData, ttl));
+ }
+
+ public void remove()
+ throws DNSSDException
+ {
+ this.ThrowOnErr( this.Remove());
+ }
+
+ protected long fRecord; // Really a DNSRecord; sizeof(int) == sizeof(void*) ?
+ protected AppleService fOwner;
+
+ protected void ThrowOnErr( int rc) throws DNSSDException
+ {
+ if ( rc != 0)
+ throw new AppleDNSSDException( rc);
+ }
+
+ protected native int Update( int flags, byte[] rData, int ttl);
+
+ protected native int Remove();
+}
+
+class AppleRegistration extends AppleService implements DNSSDRegistration
+{
+ public AppleRegistration( int flags, int ifIndex, String serviceName, String regType, String domain,
+ String host, int port, byte[] txtRecord, RegisterListener client)
+ throws DNSSDException
+ {
+ super(client);
+ this.ThrowOnErr( this.BeginRegister( ifIndex, flags, serviceName, regType, domain, host, port, txtRecord));
+ if ( !AppleDNSSD.hasAutoCallbacks)
+ new Thread(this).start();
+ }
+
+ public DNSRecord addRecord( int flags, int rrType, byte[] rData, int ttl)
+ throws DNSSDException
+ {
+ AppleDNSRecord newRecord = new AppleDNSRecord( this);
+
+ this.ThrowOnErr( this.AddRecord( flags, rrType, rData, ttl, newRecord));
+ return newRecord;
+ }
+
+ public DNSRecord getTXTRecord()
+ throws DNSSDException
+ {
+ return new AppleDNSRecord( this); // A record with ref 0 is understood to be primary TXT record
+ }
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int BeginRegister( int ifIndex, int flags, String serviceName, String regType,
+ String domain, String host, int port, byte[] txtRecord);
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int AddRecord( int flags, int rrType, byte[] rData, int ttl, AppleDNSRecord destObj);
+}
+
+class AppleRecordRegistrar extends AppleService implements DNSSDRecordRegistrar
+{
+ public AppleRecordRegistrar( RegisterRecordListener listener)
+ throws DNSSDException
+ {
+ super(listener);
+ this.ThrowOnErr( this.CreateConnection());
+ if ( !AppleDNSSD.hasAutoCallbacks)
+ new Thread(this).start();
+ }
+
+ public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype,
+ int rrclass, byte[] rdata, int ttl)
+ throws DNSSDException
+ {
+ AppleDNSRecord newRecord = new AppleDNSRecord( this);
+
+ this.ThrowOnErr( this.RegisterRecord( flags, ifIndex, fullname, rrtype, rrclass, rdata, ttl, newRecord));
+ return newRecord;
+ }
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int CreateConnection();
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int RegisterRecord( int flags, int ifIndex, String fullname, int rrtype,
+ int rrclass, byte[] rdata, int ttl, AppleDNSRecord destObj);
+}
+
+class AppleQuery extends AppleService
+{
+ public AppleQuery( int flags, int ifIndex, String serviceName, int rrtype,
+ int rrclass, QueryListener client)
+ throws DNSSDException
+ {
+ super(client);
+ this.ThrowOnErr( this.CreateQuery( flags, ifIndex, serviceName, rrtype, rrclass));
+ if ( !AppleDNSSD.hasAutoCallbacks)
+ new Thread(this).start();
+ }
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int CreateQuery( int flags, int ifIndex, String serviceName, int rrtype, int rrclass);
+}
+
+class AppleDomainEnum extends AppleService
+{
+ public AppleDomainEnum( int flags, int ifIndex, DomainListener client)
+ throws DNSSDException
+ {
+ super(client);
+ this.ThrowOnErr( this.BeginEnum( flags, ifIndex));
+ if ( !AppleDNSSD.hasAutoCallbacks)
+ new Thread(this).start();
+ }
+
+ // Sets fNativeContext. Returns non-zero on error.
+ protected native int BeginEnum( int flags, int ifIndex);
+}
+
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java
new file mode 100644
index 0000000000..618128f31f
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java
@@ -0,0 +1,76 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: DNSSDException.java,v $
+Revision 1.4 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.3 2005/07/10 22:19:01 cheshire
+Add missing error codes to list of public static final ints
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+*/
+
+package com.apple.dnssd;
+
+
+/**
+ Used to report various DNS-SD-related error conditions.
+*/
+
+abstract public class DNSSDException extends Exception
+{
+ public static final int NO_ERROR = 0;
+ public static final int UNKNOWN = -65537;
+ public static final int NO_SUCH_NAME = -65538;
+ public static final int NO_MEMORY = -65539;
+ public static final int BAD_PARAM = -65540;
+ public static final int BAD_REFERENCE = -65541;
+ public static final int BAD_STATE = -65542;
+ public static final int BAD_FLAGS = -65543;
+ public static final int UNSUPPORTED = -65544;
+ public static final int NOT_INITIALIZED = -65545;
+ public static final int NO_CACHE = -65546;
+ public static final int ALREADY_REGISTERED = -65547;
+ public static final int NAME_CONFLICT = -65548;
+ public static final int INVALID = -65549;
+ public static final int FIREWALL = -65550;
+ public static final int INCOMPATIBLE = -65551;
+ public static final int BAD_INTERFACE_INDEX = -65552;
+ public static final int REFUSED = -65553;
+ public static final int NOSUCHRECORD = -65554;
+ public static final int NOAUTH = -65555;
+ public static final int NOSUCHKEY = -65556;
+ public static final int NATTRAVERSAL = -65557;
+ public static final int DOUBLENAT = -65558;
+ public static final int BADTIME = -65559;
+ public static final int BADSIG = -65560;
+ public static final int BADKEY = -65561;
+ public static final int TRANSIENT = -65562;
+
+ /** Returns the sub-code that identifies the particular error. */
+ abstract public int getErrorCode();
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java
new file mode 100644
index 0000000000..366d83476b
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java
@@ -0,0 +1,79 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ This file declares the public interface to DNSSDRecordRegistrar, a DNSSDService
+ subclass that allows efficient registration of multiple individual records.
+
+ Change History (most recent first):
+
+$Log: DNSSDRecordRegistrar.java,v $
+Revision 1.2 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.1 2006/06/20 23:00:12 rpantos
+<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/** An object for registering records, created by {@link DNSSD#createRecordRegistrar}. */
+
+public interface DNSSDRecordRegistrar extends DNSSDService
+{
+ /** Register an independent {@link DNSRecord}.<P>
+ @param flags
+ Possible values are SHARED or UNIQUE (see flag type definitions for details).
+ <P>
+ @param ifIndex
+ If non-zero, specifies the interface on which to register the record
+ (the index for a given interface is determined via the if_nametoindex()
+ family of calls.) Passing 0 causes the record to be registered on all interfaces.
+ <P>
+ @param fullname
+ The full domain name of the resource record.
+ <P>
+ @param rrtype
+ The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc)
+ as defined in nameser.h.
+ <P>
+ @param rrclass
+ The class of the resource record, as defined in nameser.h
+ (usually 1 for the Internet class).
+ <P>
+ @param rData
+ The new rdata as it is to appear in the DNS record.
+ <P>
+ @param ttl
+ The time to live of the resource record, in seconds. Pass 0 to use a default value.
+ <P>
+ @param listener
+ This object will get called when the service is registered.
+ <P>
+ @return A {@link DNSSDService} that can be used to abort the record registration.
+
+ @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
+ @see RuntimePermission
+ */
+ public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype,
+ int rrclass, byte[] rdata, int ttl)
+ throws DNSSDException;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java
new file mode 100644
index 0000000000..4ae38036ed
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java
@@ -0,0 +1,77 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: DNSSDRegistration.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/12/11 03:01:00 rpantos
+<rdar://problem/3907498> Java DNSRecord API should be cleaned up
+
+Revision 1.1 2004/04/30 16:32:34 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ This file declares the public interface to DNSSDRegistration, a DNSSDService
+ subclass that allows a client to control a service registration.
+ */
+
+
+package com.apple.dnssd;
+
+
+/** A tracking object for a registration created by {@link DNSSD#register}. */
+
+public interface DNSSDRegistration extends DNSSDService
+{
+ /** Get a reference to the primary TXT record of a registered service.<P>
+ The record can be updated by sending it an update() message.<P>
+
+ <P>
+ @return A {@link DNSRecord}.
+ If {@link DNSSDRegistration#stop} is called, the DNSRecord is also
+ invalidated and may not be used further.
+ */
+ DNSRecord getTXTRecord()
+ throws DNSSDException;
+
+ /** Add a record to a registered service.<P>
+ The name of the record will be the same as the registered service's name.<P>
+ The record can be updated or deregistered by sending it an update() or remove() message.<P>
+
+ @param flags
+ Currently unused, reserved for future use.
+ <P>
+ @param rrType
+ The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h.
+ <P>
+ @param rData
+ The raw rdata to be contained in the added resource record.
+ <P>
+ @param ttl
+ The time to live of the resource record, in seconds.
+ <P>
+ @return A {@link DNSRecord} that may be passed to updateRecord() or removeRecord().
+ If {@link DNSSDRegistration#stop} is called, the DNSRecord is also
+ invalidated and may not be used further.
+ */
+ DNSRecord addRecord( int flags, int rrType, byte[] rData, int ttl)
+ throws DNSSDException;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java
new file mode 100644
index 0000000000..93cc5fd2c9
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java
@@ -0,0 +1,52 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: DNSSDService.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:32:34 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+/** A tracking object for a service created by {@link DNSSD}. */
+
+public interface DNSSDService
+{
+ /**
+ Halt the active operation and free resources associated with the DNSSDService.<P>
+
+ Any services or records registered with this DNSSDService will be deregistered. Any
+ Browse, Resolve, or Query operations associated with this reference will be terminated.<P>
+
+ Note: if the service was initialized with DNSSD.register(), and an extra resource record was
+ added to the service via {@link DNSSDRegistration#addRecord}, the DNSRecord so created
+ is invalidated when this method is called - the DNSRecord may not be used afterward.
+ */
+ void stop();
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java
new file mode 100644
index 0000000000..276d5b539a
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java
@@ -0,0 +1,75 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: DomainListener.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/**
+ A listener that receives results from {@link DNSSD#enumerateDomains}.
+*/
+
+public interface DomainListener extends BaseListener
+{
+ /** Called to report discovered domains.<P>
+
+ @param domainEnum
+ The active domain enumerator.
+ @param flags
+ Possible values are: DNSSD.MORE_COMING, DNSSD.DEFAULT
+ <P>
+ @param ifIndex
+ Specifies the interface on which the domain exists. (The index for a given
+ interface is determined via the if_nametoindex() family of calls.)
+ <P>
+ @param domain
+ The name of the domain.
+ */
+ void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain);
+
+ /** Called to report that a domain has disappeared.<P>
+
+ @param domainEnum
+ The active domain enumerator.
+ @param flags
+ Possible values are: DNSSD.MORE_COMING, DNSSD.DEFAULT
+ <P>
+ @param ifIndex
+ Specifies the interface on which the domain exists. (The index for a given
+ interface is determined via the if_nametoindex() family of calls.)
+ <P>
+ @param domain
+ The name of the domain.
+ */
+ void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile b/usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile
new file mode 100644
index 0000000000..e25208d774
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile
@@ -0,0 +1,150 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+DNSSD_PKG = com.apple.dnssd
+
+TOP = $(SRC)/lib/libdns_sd/java
+JAVASRCDIR = $(TOP)/com/apple/dnssd
+CLASSPATH = $(TOP):com/apple/dnssd
+
+JAVAFLAGS += -source 1.4 -target 1.4
+SOURCE:sh = ls *.java
+CLASSES = $(SOURCE:java=class)
+JNIH = DNSSD.java.h
+JAR_FILE = dnssd.jar
+
+DOCDIR = $(JAVASRCDIR)/docs
+DOCAPIDIR = $(JAVASRCDIR)/docs/api
+DOCDESTDIR = $(ROOTDNSSDJAVAHOME)/javadoc/dnssd
+DOCAPIDESTDIR = $(DOCDESTDIR)/api
+DOCEXAMPLESDESTDIR = $(DOCDESTDIR)/examples
+
+EXAMPLESDIR = $(JAVASRCDIR)/docs/examples
+EXAMPLESSRC = $(JAVASRCDIR)/docs/examples/src
+SIMPLECHATOBJ = $(EXAMPLESDIR)/SwingBrowseListener.class \
+ $(EXAMPLESDIR)/SwingQueryListener.class \
+ $(EXAMPLESDIR)/SimpleChat.class
+BROWSERAPPOBJ = $(EXAMPLESDIR)/SwingResolveListener.class \
+ $(EXAMPLESDIR)/SwingDomainListener.class \
+ $(EXAMPLESDIR)/BrowserApp.class
+EXAMPLEOBJS = $(SIMPLECHATOBJ) $(BROWSERAPPOBJ)
+EXAMPLEJARS = SimpleChat.jar BrowserApp.jar
+
+INSTALL_JAR = $(ROOTDNSSDJAVAHOME)/$(JAR_FILE)
+INSTALL_EXAMPLEJARS = $(DOCEXAMPLESDESTDIR)/SimpleChat.jar \
+ $(DOCEXAMPLESDESTDIR)/BrowserApp.jar
+
+CLEAN_FILES = *.class $(JNIH) *.jar $(EXAMPLESDIR)/*.class $(EXAMPLESDIR)/*.jar
+
+DEFINES=
+
+INCLUDES= -I${JAVA_HOME}/include \
+ -I${JAVA_HOME}/include/solaris
+
+.KEEP_STATE:
+
+all: $(JNIH) $(CLASSES) $(EXAMPLEOBJS) doc
+
+install: $(CLASSES) $(ROOTDNSSDJAVAHOME) \
+ $(DOCEXAMPLESDESTDIR) $(DOCEXAMPLESSRCDESTDIR) \
+ $(JAR_FILE) $(INSTALL_JAR) $(JNIH) \
+ $(EXAMPLEJARS) $(INSTALL_EXAMPLEJARS) \
+ install_doc
+
+$(JNIH): $(CLASSES)
+ class="com.apple.dnssd.AppleDNSSD \
+ com.apple.dnssd.AppleBrowser \
+ com.apple.dnssd.AppleResolver \
+ com.apple.dnssd.AppleRegistration \
+ com.apple.dnssd.AppleQuery \
+ com.apple.dnssd.AppleDomainEnum \
+ com.apple.dnssd.AppleService"; \
+ $(JAVAH) -classpath $(CLASSPATH) -jni -o $(JNIH) $$class
+
+clean clobber:
+ $(RM) $(CLEAN_FILES)
+
+$(JAR_FILE): $(CLASSES)
+ cd $(TOP); \
+ $(JAR) -cvf $(TOP)/com/apple/dnssd/$(JAR_FILE) com/apple/dnssd/*.class
+
+$(EXAMPLESDIR)/%.class: $(EXAMPLESSRC)/%.java
+ $(JAVAC) $(JAVAFLAGS) $< -classpath $(CLASSPATH):$(EXAMPLESDIR) -d $(EXAMPLESDIR)
+
+SIMPLECHATMAN = $(EXAMPLESSRC)/SimpleChat.manifest
+
+SimpleChat.jar: $(SIMPLECHATOBJ) $(SIMPLECHATMAN)
+ cd $(EXAMPLESDIR); $(JAR) -cvfm $@ $(SIMPLECHATMAN) \
+ SwingBrowseListener.class SwingQueryListener.class \
+ SimpleChat.class SimpleChat\$$1.class \
+ ListenerThread.class TargetListElem.class \
+ TargetListModel.class src/SimpleChat.java \
+ src/SimpleChat.manifest src/SwingBrowseListener.java \
+ src/SwingQueryListener.java
+
+BROWSERAPPMAN = $(EXAMPLESSRC)/BrowserApp.manifest
+
+BrowserApp.jar: $(BROWSERAPPOBJ) $(BROWSERAPPMAN)
+ cd $(EXAMPLESDIR); $(JAR) -cvfm $@ $(BROWSERAPPMAN) \
+ BrowserApp\$$1.class BrowserApp.class \
+ BrowserListModel\$$BrowserListElem.class \
+ BrowserListModel.class DomainListModel.class \
+ ServicesBrowserListModel.class \
+ SwingResolveListener.class SwingDomainListener.class \
+ src/BrowserApp.java src/SwingResolveListener.java \
+ src/SwingDomainListener.java src/BrowserApp.manifest
+
+$(ROOTDNSSDJAVAHOME):
+ $(INS.dir)
+
+$(ROOTDNSSDJAVAHOME)/%: %
+ $(INS.file)
+
+$(DOCDESTDIR):
+ $(INS.dir)
+
+$(DOCAPIDESTDIR): $(DOCDESTDIR)
+ $(INS.dir)
+
+$(DOCEXAMPLESDESTDIR): $(DOCDESTDIR)
+ $(INS.dir)
+
+$(DOCEXAMPLESDESTDIR)/%: %
+ $(RM) $@; $(INS) -s -m $(FILEMODE) -f $(@D) $(EXAMPLESDIR)/$<
+
+install_doc: $(CLASSES) $(DOCAPIDESTDIR)
+ -$(RM) -r $(DOCAPIDESTDIR)/*
+ cd $(TOP); umask 022; \
+ $(JAVADOC) $(JAVASRCDIR)/*.java -classpath $(CLASSPATH) -d \
+ $(DOCAPIDESTDIR) -public $(DNSSD_PKG)
+
+doc:
+ -@mkdir -p $(DOCAPIDIR)
+ cd $(TOP); umask 022; \
+ $(JAVADOC) $(JAVASRCDIR)/*.java -classpath $(CLASSPATH) -d \
+ $(DOCAPIDIR) -public $(DNSSD_PKG)
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java
new file mode 100644
index 0000000000..7978dda42f
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java
@@ -0,0 +1,71 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: QueryListener.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/** A listener that receives results from {@link DNSSD#queryRecord}. */
+
+public interface QueryListener extends BaseListener
+{
+ /** Called when a record query has been completed.<P>
+
+ @param query
+ The active query object.
+ <P>
+ @param flags
+ Possible values are DNSSD.MORE_COMING.
+ <P>
+ @param ifIndex
+ The interface on which the query was resolved. (The index for a given
+ interface is determined via the if_nametoindex() family of calls.)
+ <P>
+ @param fullName
+ The resource record's full domain name.
+ <P>
+ @param rrtype
+ The resource record's type (e.g. PTR, SRV, etc) as defined by RFC 1035 and its updates.
+ <P>
+ @param rrclass
+ The class of the resource record, as defined by RFC 1035 and its updates.
+ <P>
+ @param rdata
+ The raw rdata of the resource record.
+ <P>
+ @param ttl
+ The resource record's time to live, in seconds.
+ */
+ void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName,
+ int rrtype, int rrclass, byte[] rdata, int ttl);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java
new file mode 100644
index 0000000000..d40b6f3e75
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java
@@ -0,0 +1,64 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: RegisterListener.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/** A listener that receives results from {@link DNSSD#register}. */
+
+public interface RegisterListener extends BaseListener
+{
+ /** Called when a registration has been completed.<P>
+
+ @param registration
+ The active registration.
+ <P>
+ @param flags
+ Currently unused, reserved for future use.
+ <P>
+ @param serviceName
+ The service name registered (if the application did not specify a name in
+ DNSSD.register(), this indicates what name was automatically chosen).
+ <P>
+ @param regType
+ The type of service registered, as it was passed to DNSSD.register().
+ <P>
+ @param domain
+ The domain on which the service was registered. If the application did not
+ specify a domain in DNSSD.register(), this is the default domain
+ on which the service was registered.
+ */
+ void serviceRegistered( DNSSDRegistration registration, int flags, String serviceName,
+ String regType, String domain);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java
new file mode 100644
index 0000000000..6b8c757ae3
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java
@@ -0,0 +1,49 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: RegisterRecordListener.java,v $
+Revision 1.2 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.1 2006/06/20 23:00:12 rpantos
+<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+package com.apple.dnssd;
+
+
+/** A listener that receives results from {@link DNSSDRecordRegistrar#registerRecord}. */
+
+public interface RegisterRecordListener extends BaseListener
+{
+ /** Called when a record registration succeeds.<P>
+
+ @param record
+ A {@link DNSRecord}.
+ <P>
+ @param flags
+ Currently ignored, reserved for future use.
+ <P>
+ */
+ void recordRegistered( DNSRecord record, int flags);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java
new file mode 100644
index 0000000000..4589f53915
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java
@@ -0,0 +1,71 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: ResolveListener.java,v $
+Revision 1.3 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+*/
+
+
+package com.apple.dnssd;
+
+
+/** A listener that receives results from {@link DNSSD#resolve}. */
+
+public interface ResolveListener extends BaseListener
+{
+ /** Called when a service has been resolved.<P>
+
+ @param resolver
+ The active resolver object.
+ <P>
+ @param flags
+ Currently unused, reserved for future use.
+ <P>
+ @param fullName
+ The full service domain name, in the form &lt;servicename&gt;.&lt;protocol&gt;.&lt;domain&gt;.
+ (Any literal dots (".") are escaped with a backslash ("\."), and literal
+ backslashes are escaped with a second backslash ("\\"), e.g. a web server
+ named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local.").
+ This is the appropriate format to pass to standard system DNS APIs such as
+ res_query(), or to the special-purpose functions included in this API that
+ take fullname parameters.
+ <P>
+ @param hostName
+ The target hostname of the machine providing the service. This name can
+ be passed to functions like queryRecord() to look up the host's IP address.
+ <P>
+ @param port
+ The port number on which connections are accepted for this service.
+ <P>
+ @param txtRecord
+ The service's primary txt record.
+ */
+ void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName,
+ String hostName, int port, TXTRecord txtRecord);
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java
new file mode 100644
index 0000000000..c1c5f0b3b7
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java
@@ -0,0 +1,313 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: TXTRecord.java,v $
+Revision 1.6 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.5 2004/08/25 21:54:36 rpantos
+<rdar://problem/3773973> Fix getValue() for values containing '='.
+
+Revision 1.4 2004/08/04 01:04:50 rpantos
+<rdar://problems/3731579&3731582> Fix set(); add remove() & toString().
+
+Revision 1.3 2004/07/13 21:24:25 rpantos
+Fix for <rdar://problem/3701120>.
+
+Revision 1.2 2004/04/30 21:48:27 rpantos
+Change line endings for CVS.
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ To do:
+ - implement remove()
+ - fix set() to replace existing values
+ */
+
+
+package com.apple.dnssd;
+
+
+/**
+ Object used to construct and parse DNS-SD format TXT records.
+ For more info see <a href="http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt">DNS-Based Service Discovery</a>, section 6.
+*/
+
+public class TXTRecord
+{
+ /*
+ DNS-SD specifies that a TXT record corresponding to an SRV record consist of
+ a packed array of bytes, each preceded by a length byte. Each string
+ is an attribute-value pair.
+
+ The TXTRecord object stores the entire TXT data as a single byte array, traversing it
+ as need be to implement its various methods.
+ */
+
+ static final protected byte kAttrSep = '=';
+
+ protected byte[] fBytes;
+
+ /** Constructs a new, empty TXT record. */
+ public TXTRecord()
+ { fBytes = new byte[0]; }
+
+ /** Constructs a new TXT record from a byte array in the standard format. */
+ public TXTRecord( byte[] initBytes)
+ { fBytes = (byte[]) initBytes.clone(); }
+
+ /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
+ @param key
+ The key name. Must be ASCII, with no '=' characters.
+ <P>
+ @param value
+ Value to be encoded into bytes using the default platform character set.
+ */
+ public void set( String key, String value)
+ {
+ byte[] valBytes = (value != null) ? value.getBytes() : null;
+ this.set( key, valBytes);
+ }
+
+ /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
+ @param key
+ The key name. Must be ASCII, with no '=' characters.
+ <P>
+ @param value
+ Binary representation of the value.
+ */
+ public void set( String key, byte[] value)
+ {
+ byte[] keyBytes;
+ int valLen = (value != null) ? value.length : 0;
+
+ try {
+ keyBytes = key.getBytes( "US-ASCII");
+ }
+ catch ( java.io.UnsupportedEncodingException uee) {
+ throw new IllegalArgumentException();
+ }
+
+ for ( int i=0; i < keyBytes.length; i++)
+ if ( keyBytes[i] == '=')
+ throw new IllegalArgumentException();
+
+ if ( keyBytes.length + valLen >= 255)
+ throw new ArrayIndexOutOfBoundsException();
+
+ int prevLoc = this.remove( key);
+ if ( prevLoc == -1)
+ prevLoc = this.size();
+
+ this.insert( keyBytes, value, prevLoc);
+ }
+
+ protected void insert( byte[] keyBytes, byte[] value, int index)
+ // Insert a key-value pair at index
+ {
+ byte[] oldBytes = fBytes;
+ int valLen = (value != null) ? value.length : 0;
+ int insertion = 0;
+ byte newLen, avLen;
+
+ // locate the insertion point
+ for ( int i=0; i < index && insertion < fBytes.length; i++)
+ insertion += fBytes[ insertion] + 1;
+
+ avLen = (byte) ( keyBytes.length + valLen + (value != null ? 1 : 0));
+ newLen = (byte) ( avLen + oldBytes.length + 1);
+
+ fBytes = new byte[ newLen];
+ System.arraycopy( oldBytes, 0, fBytes, 0, insertion);
+ int secondHalfLen = oldBytes.length - insertion;
+ System.arraycopy( oldBytes, insertion, fBytes, newLen - secondHalfLen, secondHalfLen);
+ fBytes[ insertion] = avLen;
+ System.arraycopy( keyBytes, 0, fBytes, insertion + 1, keyBytes.length);
+ if ( value != null)
+ {
+ fBytes[ insertion + 1 + keyBytes.length] = kAttrSep;
+ System.arraycopy( value, 0, fBytes, insertion + keyBytes.length + 2, valLen);
+ }
+ }
+
+ /** Remove a key/value pair from the TXT record. Returns index it was at, or -1 if not found. */
+ public int remove( String key)
+ {
+ int avStart = 0;
+
+ for ( int i=0; avStart < fBytes.length; i++)
+ {
+ int avLen = fBytes[ avStart];
+ if ( key.length() <= avLen &&
+ ( key.length() == avLen || fBytes[ avStart + key.length() + 1] == kAttrSep))
+ {
+ String s = new String( fBytes, avStart + 1, key.length());
+ if ( 0 == key.compareToIgnoreCase( s))
+ {
+ byte[] oldBytes = fBytes;
+ fBytes = new byte[ oldBytes.length - avLen - 1];
+ System.arraycopy( oldBytes, 0, fBytes, 0, avStart);
+ System.arraycopy( oldBytes, avStart + avLen + 1, fBytes, avStart, oldBytes.length - avStart - avLen - 1);
+ return i;
+ }
+ }
+ avStart += avLen + 1;
+ }
+ return -1;
+ }
+
+ /** Return the number of keys in the TXT record. */
+ public int size()
+ {
+ int i, avStart;
+
+ for ( i=0, avStart=0; avStart < fBytes.length; i++)
+ avStart += fBytes[ avStart] + 1;
+ return i;
+ }
+
+ /** Return true if key is present in the TXT record, false if not. */
+ public boolean contains( String key)
+ {
+ String s = null;
+
+ for ( int i=0; null != ( s = this.getKey( i)); i++)
+ if ( 0 == key.compareToIgnoreCase( s))
+ return true;
+ return false;
+ }
+
+ /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */
+ public String getKey( int index)
+ {
+ int avStart = 0;
+
+ for ( int i=0; i < index && avStart < fBytes.length; i++)
+ avStart += fBytes[ avStart] + 1;
+
+ if ( avStart < fBytes.length)
+ {
+ int avLen = fBytes[ avStart];
+ int aLen = 0;
+
+ for ( aLen=0; aLen < avLen; aLen++)
+ if ( fBytes[ avStart + aLen + 1] == kAttrSep)
+ break;
+ return new String( fBytes, avStart + 1, aLen);
+ }
+ return null;
+ }
+
+ /**
+ Look up a key in the TXT record by zero-based index and return its value. <P>
+ Returns null if index exceeds the total number of keys.
+ Returns null if the key is present with no value.
+ */
+ public byte[] getValue( int index)
+ {
+ int avStart = 0;
+ byte[] value = null;
+
+ for ( int i=0; i < index && avStart < fBytes.length; i++)
+ avStart += fBytes[ avStart] + 1;
+
+ if ( avStart < fBytes.length)
+ {
+ int avLen = fBytes[ avStart];
+ int aLen = 0;
+
+ for ( aLen=0; aLen < avLen; aLen++)
+ {
+ if ( fBytes[ avStart + aLen + 1] == kAttrSep)
+ {
+ value = new byte[ avLen - aLen - 1];
+ System.arraycopy( fBytes, avStart + aLen + 2, value, 0, avLen - aLen - 1);
+ break;
+ }
+ }
+ }
+ return value;
+ }
+
+ /** Converts the result of getValue() to a string in the platform default character set. */
+ public String getValueAsString( int index)
+ {
+ byte[] value = this.getValue( index);
+ return value != null ? new String( value) : null;
+ }
+
+ /** Get the value associated with a key. Will be null if the key is not defined.
+ Array will have length 0 if the key is defined with an = but no value.<P>
+
+ @param forKey
+ The left-hand side of the key-value pair.
+ <P>
+ @return The binary representation of the value.
+ */
+ public byte[] getValue( String forKey)
+ {
+ String s = null;
+ int i;
+
+ for ( i=0; null != ( s = this.getKey( i)); i++)
+ if ( 0 == forKey.compareToIgnoreCase( s))
+ return this.getValue( i);
+ return null;
+ }
+
+ /** Converts the result of getValue() to a string in the platform default character set.<P>
+
+ @param forKey
+ The left-hand side of the key-value pair.
+ <P>
+ @return The value represented in the default platform character set.
+ */
+ public String getValueAsString( String forKey)
+ {
+ byte[] val = this.getValue( forKey);
+ return val != null ? new String( val) : null;
+ }
+
+ /** Return the contents of the TXT record as raw bytes. */
+ public byte[] getRawBytes() { return (byte[]) fBytes.clone(); }
+
+ /** Return a string representation of the object. */
+ public String toString()
+ {
+ String a, result = null;
+
+ for ( int i=0; null != ( a = this.getKey( i)); i++)
+ {
+ String av = String.valueOf( i) + "={" + a;
+ String val = this.getValueAsString( i);
+ if ( val != null)
+ av += "=" + val + "}";
+ else
+ av += "}";
+ if ( result == null)
+ result = av;
+ else
+ result = result + ", " + av;
+ }
+ return result != null ? result : "";
+ }
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java
new file mode 100644
index 0000000000..381657151b
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java
@@ -0,0 +1,400 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms. If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software. Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple. Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ BrowserApp demonstrates how to use DNS-SD to browse for and resolve services.
+
+ To do:
+ - display resolved TXTRecord
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.text.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import com.apple.dnssd.*;
+
+
+class BrowserApp implements ListSelectionListener, ResolveListener
+{
+ static BrowserApp app;
+ JFrame frame;
+ DomainListModel domainList;
+ BrowserListModel servicesList, serviceList;
+ JList domainPane, servicesPane, servicePane;
+ DNSSDService servicesBrowser, serviceBrowser, domainBrowser;
+ JLabel hostLabel, portLabel;
+
+ public BrowserApp()
+ {
+ frame = new JFrame("DNS-SD Service Browser");
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {System.exit(0);}
+ });
+
+ domainList = new DomainListModel();
+ servicesList = new ServicesBrowserListModel();
+ serviceList = new BrowserListModel();
+
+ try {
+ domainBrowser = DNSSD.enumerateDomains( DNSSD.BROWSE_DOMAINS, 0, domainList);
+
+ servicesBrowser = DNSSD.browse( 0, 0, "_services._dns-sd._udp.", "", servicesList);
+ serviceBrowser = null;
+ }
+ catch ( Exception ex) { terminateWithException( ex); }
+
+ this.setupSubPanes( frame.getContentPane());
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ protected void setupSubPanes( Container parent)
+ {
+ parent.setLayout( new BoxLayout( parent, BoxLayout.Y_AXIS));
+
+ JPanel browserRow = new JPanel();
+ browserRow.setLayout( new BoxLayout( browserRow, BoxLayout.X_AXIS));
+ domainPane = new JList( domainList);
+ domainPane.addListSelectionListener( this);
+ JScrollPane domainScroller = new JScrollPane( domainPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ browserRow.add( domainScroller);
+ servicesPane = new JList( servicesList);
+ servicesPane.addListSelectionListener( this);
+ JScrollPane servicesScroller = new JScrollPane( servicesPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ browserRow.add( servicesScroller);
+ servicePane = new JList( serviceList);
+ servicePane.addListSelectionListener( this);
+ JScrollPane serviceScroller = new JScrollPane( servicePane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ browserRow.add( serviceScroller);
+
+/*
+ JPanel buttonRow = new JPanel();
+ buttonRow.setLayout( new BoxLayout( buttonRow, BoxLayout.X_AXIS));
+ buttonRow.add( Box.createHorizontalGlue());
+ JButton connectButton = new JButton( "Don't Connect");
+ buttonRow.add( connectButton);
+ buttonRow.add( Box.createRigidArea( new Dimension( 16, 0)));
+*/
+
+ JPanel labelRow = new JPanel();
+ labelRow.setLayout( new BoxLayout( labelRow, BoxLayout.X_AXIS));
+ labelRow.add( new JLabel( " Host: "));
+ hostLabel = new JLabel();
+ labelRow.add( hostLabel);
+ labelRow.add( Box.createRigidArea( new Dimension( 32, 0)));
+ labelRow.add( new JLabel( "Port: "));
+ portLabel = new JLabel();
+ labelRow.add( portLabel);
+ labelRow.add( Box.createHorizontalGlue());
+
+ parent.add( browserRow);
+ parent.add( Box.createRigidArea( new Dimension( 0, 8)));
+ parent.add( labelRow);
+// parent.add( buttonRow);
+ parent.add( Box.createRigidArea( new Dimension( 0, 16)));
+ }
+
+ public void valueChanged( ListSelectionEvent e)
+ {
+ try {
+ if ( e.getSource() == domainPane && !e.getValueIsAdjusting())
+ {
+ int newSel = domainPane.getSelectedIndex();
+ if ( -1 != newSel)
+ {
+ if ( serviceBrowser != null)
+ serviceBrowser.stop();
+ serviceList.removeAllElements();
+ servicesBrowser = DNSSD.browse( 0, 0, "_services._dns-sd._udp.", "", servicesList);
+ }
+ }
+ else if ( e.getSource() == servicesPane && !e.getValueIsAdjusting())
+ {
+ int newSel = servicesPane.getSelectedIndex();
+ if ( serviceBrowser != null)
+ serviceBrowser.stop();
+ serviceList.removeAllElements();
+ if ( -1 != newSel)
+ serviceBrowser = DNSSD.browse( 0, 0, servicesList.getNthRegType( newSel), "", serviceList);
+ }
+ else if ( e.getSource() == servicePane && !e.getValueIsAdjusting())
+ {
+ int newSel = servicePane.getSelectedIndex();
+
+ hostLabel.setText( "");
+ portLabel.setText( "");
+
+ if ( -1 != newSel)
+ {
+ DNSSD.resolve( 0, serviceList.getNthInterface( newSel),
+ serviceList.getNthServiceName( newSel),
+ serviceList.getNthRegType( newSel),
+ serviceList.getNthDomain( newSel),
+ new SwingResolveListener( this));
+ }
+ }
+ }
+ catch ( Exception ex) { terminateWithException( ex); }
+ }
+
+ public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName,
+ String hostName, int port, TXTRecord txtRecord)
+ {
+ hostLabel.setText( hostName);
+ portLabel.setText( String.valueOf( port));
+ }
+
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ // handle failure here
+ }
+
+ protected static void terminateWithException( Exception e)
+ {
+ e.printStackTrace();
+ System.exit( -1);
+ }
+
+ public static void main(String s[])
+ {
+ app = new BrowserApp();
+ }
+}
+
+
+class BrowserListModel extends DefaultListModel implements BrowseListener, Runnable
+{
+ public BrowserListModel()
+ {
+ addCache = new Vector();
+ removeCache = new Vector();
+ }
+
+ /* The Browser invokes this callback when a service is discovered. */
+ public void serviceFound( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ {
+ addCache.add( new BrowserListElem( serviceName, domain, regType, ifIndex));
+ if ( ( flags & DNSSD.MORE_COMING) == 0)
+ this.scheduleOnEventThread();
+ }
+
+ public void serviceLost( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ {
+ removeCache.add( serviceName);
+ if ( ( flags & DNSSD.MORE_COMING) == 0)
+ this.scheduleOnEventThread();
+ }
+
+ public void run()
+ {
+ while ( removeCache.size() > 0)
+ {
+ String serviceName = (String) removeCache.remove( removeCache.size() - 1);
+ int matchInd = this.findMatching( serviceName); // probably doesn't handle near-duplicates well.
+ if ( matchInd != -1)
+ this.removeElementAt( matchInd);
+ }
+ while ( addCache.size() > 0)
+ {
+ BrowserListElem elem = (BrowserListElem) addCache.remove( addCache.size() - 1);
+ if ( -1 == this.findMatching( elem.fServiceName)) // probably doesn't handle near-duplicates well.
+ this.addInSortOrder( elem);
+ }
+ }
+
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ // handle failure here
+ }
+
+ /* The list contains BrowserListElem's */
+ class BrowserListElem
+ {
+ public BrowserListElem( String serviceName, String domain, String type, int ifIndex)
+ { fServiceName = serviceName; fDomain = domain; fType = type; fInt = ifIndex; }
+
+ public String toString() { return fServiceName; }
+
+ public String fServiceName, fDomain, fType;
+ public int fInt;
+ }
+
+ public String getNthServiceName( int n)
+ {
+ BrowserListElem sel = (BrowserListElem) this.get( n);
+ return sel.fServiceName;
+ }
+
+ public String getNthRegType( int n)
+ {
+ BrowserListElem sel = (BrowserListElem) this.get( n);
+ return sel.fType;
+ }
+
+ public String getNthDomain( int n)
+ {
+ BrowserListElem sel = (BrowserListElem) this.get( n);
+ return sel.fDomain;
+ }
+
+ public int getNthInterface( int n)
+ {
+ BrowserListElem sel = (BrowserListElem) this.get( n);
+ return sel.fInt;
+ }
+
+ protected void addInSortOrder( Object obj)
+ {
+ int i;
+ for ( i = 0; i < this.size(); i++)
+ if ( sCollator.compare( obj.toString(), this.getElementAt( i).toString()) < 0)
+ break;
+ this.add( i, obj);
+ }
+
+ protected int findMatching( String match)
+ {
+ for ( int i = 0; i < this.size(); i++)
+ if ( match.equals( this.getElementAt( i).toString()))
+ return i;
+ return -1;
+ }
+
+ protected void scheduleOnEventThread()
+ {
+ try {
+ SwingUtilities.invokeAndWait( this);
+ }
+ catch ( Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected Vector removeCache; // list of serviceNames to remove
+ protected Vector addCache; // list of BrowserListElem's to add
+
+ protected static Collator sCollator;
+
+ static // Initialize our static variables
+ {
+ sCollator = Collator.getInstance();
+ sCollator.setStrength( Collator.PRIMARY);
+ }
+}
+
+
+class ServicesBrowserListModel extends BrowserListModel
+{
+ /* The Browser invokes this callback when a service is discovered. */
+ public void serviceFound( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ // Overridden to stuff serviceName into regType and make serviceName human-readable.
+ {
+ regType = serviceName + ( regType.startsWith( "_udp.") ? "._udp." : "._tcp.");
+ super.serviceFound( browser, flags, ifIndex, this.mapTypeToName( serviceName), regType, domain);
+ }
+
+ public void serviceLost( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ // Overridden to make serviceName human-readable.
+ {
+ super.serviceLost( browser, flags, ifIndex, this.mapTypeToName( serviceName), regType, domain);
+ }
+
+ protected String mapTypeToName( String type)
+ // Convert a registration type into a human-readable string. Returns original string on no-match.
+ {
+ final String[] namedServices = {
+ "_afpovertcp", "Apple File Sharing",
+ "_http", "World Wide Web servers",
+ "_daap", "Digital Audio Access",
+ "_apple-sasl", "Apple Password Servers",
+ "_distcc", "Distributed Compiler nodes",
+ "_finger", "Finger servers",
+ "_ichat", "iChat clients",
+ "_presence", "iChat AV clients",
+ "_ssh", "SSH servers",
+ "_telnet", "Telnet servers",
+ "_workstation", "Macintosh Manager clients",
+ "_bootps", "BootP servers",
+ "_xserveraid", "XServe RAID devices",
+ "_eppc", "Remote AppleEvents",
+ "_ftp", "FTP services",
+ "_tftp", "TFTP services"
+ };
+
+ for ( int i = 0; i < namedServices.length; i+=2)
+ if ( namedServices[i].equals( type))
+ return namedServices[i + 1];
+ return type;
+ }
+}
+
+
+class DomainListModel extends DefaultListModel implements DomainListener
+{
+ /* Called when a domain is discovered. */
+ public void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain)
+ {
+ if ( !this.contains( domain))
+ this.addElement( domain);
+ }
+
+ public void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain)
+ {
+ if ( this.contains( domain))
+ this.removeElement( domain);
+ }
+
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ // handle failure here
+ }
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest
new file mode 100644
index 0000000000..472b17f638
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: BrowserApp
+Class-Path: /usr/share/lib/java/dnssd.jar
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java
new file mode 100644
index 0000000000..62dd11faa5
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java
@@ -0,0 +1,336 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms. If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software. Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple. Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ SimpleChat is a simple peer-to-peer chat program that demonstrates
+ DNS-SD registration, browsing, resolving and record-querying.
+
+ To do:
+ - implement better coloring algorithm
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.text.*;
+import java.net.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+
+import com.apple.dnssd.*;
+
+
+class SimpleChat implements ResolveListener, RegisterListener, QueryListener,
+ ActionListener, ItemListener, Runnable
+{
+ Document textDoc; // Holds all the chat text
+ JTextField inputField; // Holds a pending chat response
+ String ourName; // name used to identify this user in chat
+ DNSSDService browser; // object that actively browses for other chat clients
+ DNSSDService resolver; // object that resolves other chat clients
+ DNSSDRegistration registration; // object that maintains our connection advertisement
+ JComboBox targetPicker; // Indicates who we're talking to
+ TargetListModel targetList; // and its list model
+ JButton sendButton; // Will send text in inputField to target
+ InetAddress buddyAddr; // and address
+ int buddyPort; // and port
+ DatagramPacket dataPacket; // Inbound data packet
+ DatagramSocket outSocket; // Outbound data socket
+ SimpleAttributeSet textAttribs;
+
+ static final String kChatExampleRegType = "_p2pchat._udp";
+ static final String kWireCharSet = "ISO-8859-1";
+
+ public SimpleChat() throws Exception
+ {
+ JFrame frame = new JFrame("SimpleChat");
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {System.exit(0);}
+ });
+
+ ourName = System.getProperty( "user.name");
+ targetList = new TargetListModel();
+ textAttribs = new SimpleAttributeSet();
+ DatagramSocket inSocket = new DatagramSocket();
+ dataPacket = new DatagramPacket( new byte[ 4096], 4096);
+ outSocket = new DatagramSocket();
+
+ this.setupSubPanes( frame.getContentPane(), frame.getRootPane());
+ frame.pack();
+ frame.setVisible(true);
+ inputField.requestFocusInWindow();
+
+ browser = DNSSD.browse( 0, 0, kChatExampleRegType, "", new SwingBrowseListener( targetList));
+
+ registration = DNSSD.register( 0, 0, ourName, kChatExampleRegType, "", "", inSocket.getLocalPort(), null, this);
+
+ new ListenerThread( this, inSocket, dataPacket).start();
+ }
+
+ protected void setupSubPanes( Container parent, JRootPane rootPane)
+ {
+ parent.setLayout( new BoxLayout( parent, BoxLayout.Y_AXIS));
+
+ JPanel textRow = new JPanel();
+ textRow.setLayout( new BoxLayout( textRow, BoxLayout.X_AXIS));
+ textRow.add( Box.createRigidArea( new Dimension( 16, 0)));
+ JEditorPane textPane = new JEditorPane( "text/html", "<BR>");
+ textPane.setPreferredSize( new Dimension( 400, 300));
+ textPane.setEditable( false);
+ JScrollPane textScroller = new JScrollPane( textPane);
+ textRow.add( textScroller);
+ textRow.add( Box.createRigidArea( new Dimension( 16, 0)));
+ textDoc = textPane.getDocument();
+
+ JPanel addressRow = new JPanel();
+ addressRow.setLayout( new BoxLayout( addressRow, BoxLayout.X_AXIS));
+ targetPicker = new JComboBox( targetList);
+ targetPicker.addItemListener( this);
+ addressRow.add( Box.createRigidArea( new Dimension( 16, 0)));
+ addressRow.add( new JLabel( "Talk to: "));
+ addressRow.add( targetPicker);
+ addressRow.add( Box.createHorizontalGlue());
+
+ JPanel buttonRow = new JPanel();
+ buttonRow.setLayout( new BoxLayout( buttonRow, BoxLayout.X_AXIS));
+ buttonRow.add( Box.createRigidArea( new Dimension( 16, 0)));
+ inputField = new JTextField();
+ // prevent inputField from hijacking <Enter> key
+ inputField.getKeymap().removeKeyStrokeBinding( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0));
+ buttonRow.add( inputField);
+ sendButton = new JButton( "Send");
+ buttonRow.add( Box.createRigidArea( new Dimension( 8, 0)));
+ buttonRow.add( sendButton);
+ buttonRow.add( Box.createRigidArea( new Dimension( 16, 0)));
+ rootPane.setDefaultButton( sendButton);
+ sendButton.addActionListener( this);
+ sendButton.setEnabled( false);
+
+ parent.add( Box.createRigidArea( new Dimension( 0, 16)));
+ parent.add( textRow);
+ parent.add( Box.createRigidArea( new Dimension( 0, 8)));
+ parent.add( addressRow);
+ parent.add( Box.createRigidArea( new Dimension( 0, 8)));
+ parent.add( buttonRow);
+ parent.add( Box.createRigidArea( new Dimension( 0, 16)));
+ }
+
+ public void serviceRegistered( DNSSDRegistration registration, int flags,
+ String serviceName, String regType, String domain)
+ {
+ ourName = serviceName; // might have been renamed on collision
+ }
+
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ System.out.println( "Service reported error " + String.valueOf( errorCode));
+ }
+
+ public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName,
+ String hostName, int port, TXTRecord txtRecord)
+ {
+ buddyPort = port;
+ try {
+ // Start a record query to obtain IP address from hostname
+ DNSSD.queryRecord( 0, ifIndex, hostName, 1 /* ns_t_a */, 1 /* ns_c_in */,
+ new SwingQueryListener( this));
+ }
+ catch ( Exception e) { terminateWithException( e); }
+ resolver.stop();
+ }
+
+ public void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName,
+ int rrtype, int rrclass, byte[] rdata, int ttl)
+ {
+ try {
+ buddyAddr = InetAddress.getByAddress( rdata);
+ }
+ catch ( Exception e) { terminateWithException( e); }
+ sendButton.setEnabled( true);
+ }
+
+ public void actionPerformed( ActionEvent e) // invoked when Send button is hit
+ {
+ try
+ {
+ String sendString = ourName + ": " + inputField.getText();
+ byte[] sendData = sendString.getBytes( kWireCharSet);
+ outSocket.send( new DatagramPacket( sendData, sendData.length, buddyAddr, buddyPort));
+ StyleConstants.setForeground( textAttribs, Color.black);
+ textDoc.insertString( textDoc.getLength(), inputField.getText() + "\n", textAttribs);
+ inputField.setText( "");
+ }
+ catch ( Exception exception) { terminateWithException( exception); }
+ }
+
+ public void itemStateChanged( ItemEvent e) // invoked when Target selection changes
+ {
+ sendButton.setEnabled( false);
+ if ( e.getStateChange() == ItemEvent.SELECTED)
+ {
+ try {
+ TargetListElem sel = (TargetListElem) targetList.getSelectedItem();
+ resolver = DNSSD.resolve( 0, sel.fInt, sel.fServiceName, sel.fType, sel.fDomain, this);
+ }
+ catch ( Exception exception) { terminateWithException( exception); }
+ }
+ }
+
+ public void run() // invoked on event thread when inbound packet arrives
+ {
+ try
+ {
+ String inMessage = new String( dataPacket.getData(), 0, dataPacket.getLength(), kWireCharSet);
+ StyleConstants.setForeground( textAttribs, this.getColorFor( dataPacket.getData(), dataPacket.getLength()));
+ textDoc.insertString( textDoc.getLength(), inMessage + "\n", textAttribs);
+ }
+ catch ( Exception e) { terminateWithException( e); }
+ }
+
+ protected Color getColorFor( byte[] chars, int length)
+ // Produce a mapping from a string to a color, suitable for text display
+ {
+ int rgb = 0;
+ for ( int i=0; i < length && chars[i] != ':'; i++)
+ rgb = rgb ^ ( (int) chars[i] << (i%3+2) * 8);
+ return new Color( rgb & 0x007F7FFF); // mask off high bits so it is a dark color
+
+// for ( int i=0; i < length && chars[i] != ':'; i++)
+
+ }
+
+ protected static void terminateWithException( Exception e)
+ {
+ e.printStackTrace();
+ System.exit( -1);
+ }
+
+ public static void main(String s[])
+ {
+ try {
+ new SimpleChat();
+ }
+ catch ( Exception e) { terminateWithException( e); }
+ }
+}
+
+
+
+class TargetListElem
+{
+ public TargetListElem( String serviceName, String domain, String type, int ifIndex)
+ { fServiceName = serviceName; fDomain = domain; fType = type; fInt = ifIndex; }
+
+ public String toString() { return fServiceName; }
+
+ public String fServiceName, fDomain, fType;
+ public int fInt;
+}
+
+class TargetListModel extends DefaultComboBoxModel implements BrowseListener
+{
+ /* The Browser invokes this callback when a service is discovered. */
+ public void serviceFound( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ {
+ TargetListElem match = this.findMatching( serviceName); // probably doesn't handle near-duplicates well.
+
+ if ( match == null)
+ this.addElement( new TargetListElem( serviceName, domain, regType, ifIndex));
+ }
+
+ /* The Browser invokes this callback when a service disappears. */
+ public void serviceLost( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ {
+ TargetListElem match = this.findMatching( serviceName); // probably doesn't handle near-duplicates well.
+
+ if ( match != null)
+ this.removeElement( match);
+ }
+
+ /* The Browser invokes this callback when a service disappears. */
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ System.out.println( "Service reported error " + String.valueOf( errorCode));
+ }
+
+ protected TargetListElem findMatching( String match)
+ {
+ for ( int i = 0; i < this.getSize(); i++)
+ if ( match.equals( this.getElementAt( i).toString()))
+ return (TargetListElem) this.getElementAt( i);
+ return null;
+ }
+
+}
+
+
+// A ListenerThread runs its owner when datagram packet p appears on socket s.
+class ListenerThread extends Thread
+{
+ public ListenerThread( Runnable owner, DatagramSocket s, DatagramPacket p)
+ { fOwner = owner; fSocket = s; fPacket = p; }
+
+ public void run()
+ {
+ while ( true )
+ {
+ try
+ {
+ fSocket.receive( fPacket);
+ SwingUtilities.invokeAndWait( fOwner); // process data on main thread
+ }
+ catch( Exception e)
+ {
+ break; // terminate thread
+ }
+ }
+ }
+
+ protected Runnable fOwner;
+ protected DatagramSocket fSocket;
+ protected DatagramPacket fPacket;
+}
+
+
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest
new file mode 100644
index 0000000000..71ca6a754e
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: SimpleChat
+Class-Path: /usr/share/lib/java/dnssd.jar
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java
new file mode 100644
index 0000000000..c8ff1e6ca1
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java
@@ -0,0 +1,126 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms. If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software. Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple. Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+import javax.swing.*;
+import com.apple.dnssd.*;
+
+
+/** Use this to schedule BrowseListener callbacks via SwingUtilities.invokeAndWait(). */
+
+public class SwingBrowseListener implements Runnable, BrowseListener
+{
+ /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */
+ public SwingBrowseListener( BrowseListener listener)
+ { fListener = listener; fErrorCode = 0; }
+
+ /** (Clients should not call this method directly.) */
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ fBrowser = service;
+ fErrorCode = errorCode;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void serviceFound( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+
+ {
+ fBrowser = browser;
+ fIsAdd = true;
+ fFlags = flags;
+ fIndex = ifIndex;
+ fService = serviceName;
+ fRegType = regType;
+ fDomain = domain;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void serviceLost( DNSSDService browser, int flags, int ifIndex,
+ String serviceName, String regType, String domain)
+ {
+ fBrowser = browser;
+ fIsAdd = false;
+ fFlags = flags;
+ fIndex = ifIndex;
+ fService = serviceName;
+ fRegType = regType;
+ fDomain = domain;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void run()
+ {
+ if ( fErrorCode != 0)
+ fListener.operationFailed( fBrowser, fErrorCode);
+ else if ( fIsAdd)
+ fListener.serviceFound( fBrowser, fFlags, fIndex, fService, fRegType, fDomain);
+ else
+ fListener.serviceLost( fBrowser, fFlags, fIndex, fService, fRegType, fDomain);
+ }
+
+ protected void schedule()
+ {
+ try {
+ SwingUtilities.invokeAndWait( this);
+ }
+ catch ( Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected BrowseListener fListener;
+
+ protected boolean fIsAdd;
+ protected DNSSDService fBrowser;
+ protected int fFlags;
+ protected int fIndex;
+ protected int fErrorCode;
+ protected String fService;
+ protected String fRegType;
+ protected String fDomain;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java
new file mode 100644
index 0000000000..988591ccfc
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java
@@ -0,0 +1,119 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms. If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software. Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple. Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+import javax.swing.*;
+import com.apple.dnssd.*;
+
+
+/** Use this to schedule DomainListener callbacks via SwingUtilities.invokeAndWait(). */
+
+public class SwingDomainListener implements Runnable, DomainListener
+{
+ /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */
+ public SwingDomainListener( DomainListener listener)
+ { fListener = listener; fErrorCode = 0; }
+
+ /** (Clients should not call this method directly.) */
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ fEnumerator = service;
+ fErrorCode = errorCode;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain)
+
+ {
+ fEnumerator = domainEnum;
+ fIsAdd = true;
+ fFlags = flags;
+ fIndex = ifIndex;
+ fDomain = domain;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain)
+ {
+ fEnumerator = domainEnum;
+ fIsAdd = false;
+ fFlags = flags;
+ fIndex = ifIndex;
+ fDomain = domain;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void run()
+ {
+ if ( fErrorCode != 0)
+ fListener.operationFailed( fEnumerator, fErrorCode);
+ else if ( fIsAdd)
+ fListener.domainFound( fEnumerator, fFlags, fIndex, fDomain);
+ else
+ fListener.domainLost( fEnumerator, fFlags, fIndex, fDomain);
+ }
+
+ protected void schedule()
+ {
+ try {
+ SwingUtilities.invokeAndWait( this);
+ }
+ catch ( Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected DomainListener fListener;
+
+ protected boolean fIsAdd;
+ protected DNSSDService fEnumerator;
+ protected int fFlags;
+ protected int fIndex;
+ protected int fErrorCode;
+ protected String fDomain;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java
new file mode 100644
index 0000000000..1b301ce8e9
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java
@@ -0,0 +1,111 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms. If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software. Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple. Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+import javax.swing.*;
+import com.apple.dnssd.*;
+
+
+/** Use this to schedule QueryListener callbacks via SwingUtilities.invokeAndWait(). */
+
+public class SwingQueryListener implements Runnable, QueryListener
+{
+ /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */
+ public SwingQueryListener( QueryListener listener)
+ { fListener = listener; }
+
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ fQuery = service;
+ fErrorCode = errorCode;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName,
+ int rrtype, int rrclass, byte[] rdata, int ttl)
+ {
+ fQuery = query;
+ fFlags = flags;
+ fIndex = ifIndex;
+ fFullName = fullName;
+ fType = rrtype;
+ fClass = rrclass;
+ fData = rdata;
+ fTTL = ttl;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void run()
+ {
+ if ( fErrorCode != 0)
+ fListener.operationFailed( fQuery, fErrorCode);
+ else
+ fListener.queryAnswered( fQuery, fFlags, fIndex, fFullName, fType, fClass, fData, fTTL);
+ }
+
+ protected void schedule()
+ {
+ try {
+ SwingUtilities.invokeAndWait( this);
+ }
+ catch ( Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected QueryListener fListener;
+
+ protected DNSSDService fQuery;
+ protected int fFlags;
+ protected int fIndex;
+ protected int fErrorCode;
+ protected String fFullName;
+ protected int fType;
+ protected int fClass;
+ protected byte[] fData;
+ protected int fTTL;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java
new file mode 100644
index 0000000000..499da0707d
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java
@@ -0,0 +1,109 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ * ("Apple") in consideration of your agreement to the following terms, and your
+ * use, installation, modification or redistribution of this Apple software
+ * constitutes acceptance of these terms. If you do not agree with these terms,
+ * please do not use, install, modify or redistribute this Apple software.
+ *
+ * In consideration of your agreement to abide by the following terms, and subject
+ * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+ * copyrights in this original Apple software (the "Apple Software"), to use,
+ * reproduce, modify and redistribute the Apple Software, with or without
+ * modifications, in source and/or binary forms; provided that if you redistribute
+ * the Apple Software in its entirety and without modifications, you must retain
+ * this notice and the following text and disclaimers in all such redistributions of
+ * the Apple Software. Neither the name, trademarks, service marks or logos of
+ * Apple Computer, Inc. may be used to endorse or promote products derived from the
+ * Apple Software without specific prior written permission from Apple. Except as
+ * expressly stated in this notice, no other rights or licenses, express or implied,
+ * are granted by Apple herein, including but not limited to any patent rights that
+ * may be infringed by your derivative works or by other works in which the Apple
+ * Software may be incorporated.
+ *
+ * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ * COMBINATION WITH YOUR PRODUCTS.
+ *
+ * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ident "%Z%%M% %I% %E% SMI"
+
+ */
+
+
+import javax.swing.*;
+import com.apple.dnssd.*;
+
+
+/** Use this to schedule ResolveListener callbacks via SwingUtilities.invokeAndWait(). */
+
+public class SwingResolveListener implements Runnable, ResolveListener
+{
+ /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */
+ public SwingResolveListener( ResolveListener listener)
+ { fListener = listener; }
+
+ public void operationFailed( DNSSDService service, int errorCode)
+ {
+ fResolver = service;
+ fErrorCode = errorCode;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName,
+ String hostName, int port, TXTRecord txtRecord)
+ {
+ fResolver = resolver;
+ fFlags = flags;
+ fIndex = ifIndex;
+ fFullName = fullName;
+ fHostName = hostName;
+ fPort = port;
+ fTXTRecord = txtRecord;
+ this.schedule();
+ }
+
+ /** (Clients should not call this method directly.) */
+ public void run()
+ {
+ if ( fErrorCode != 0)
+ fListener.operationFailed( fResolver, fErrorCode);
+ else
+ fListener.serviceResolved( fResolver, fFlags, fIndex, fFullName, fHostName, fPort, fTXTRecord);
+ }
+
+ protected void schedule()
+ {
+ try {
+ SwingUtilities.invokeAndWait( this);
+ }
+ catch ( Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected ResolveListener fListener;
+
+ protected DNSSDService fResolver;
+ protected int fFlags;
+ protected int fIndex;
+ protected int fErrorCode;
+ protected String fFullName;
+ protected String fHostName;
+ protected int fPort;
+ protected TXTRecord fTXTRecord;
+}
+
diff --git a/usr/src/lib/libdns_sd/java/common/JNISupport.c b/usr/src/lib/libdns_sd/java/common/JNISupport.c
new file mode 100644
index 0000000000..bdf453475d
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/common/JNISupport.c
@@ -0,0 +1,1107 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ Change History (most recent first):
+
+$Log: JNISupport.c,v $
+Revision 1.17 2006/08/14 23:25:08 cheshire
+Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
+
+Revision 1.16 2006/07/14 02:35:47 cheshire
+Added (commented out) syslog debugging messages
+
+Revision 1.15 2006/06/27 19:34:43 cheshire
+<rdar://problem/4430023> txtRecord parameter of DNSServiceResolveReply() should be unsigned char *
+
+Revision 1.14 2006/06/20 23:03:35 rpantos
+<rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent
+
+Revision 1.13 2005/10/26 01:52:24 cheshire
+<rdar://problem/4316286> Race condition in Java code (doesn't work at all on Linux)
+
+Revision 1.12 2005/07/13 19:20:32 cheshire
+<rdar://problem/4175511> Race condition in Java API
+Additional cleanup suggested by Roger -- NewContext() doesn't need ownerClass parameter any more
+
+Revision 1.11 2005/07/11 01:55:21 cheshire
+<rdar://problem/4175511> Race condition in Java API
+
+Revision 1.10 2005/07/05 13:01:52 cheshire
+<rdar://problem/4169791> If mDNSResponder daemon is stopped, Java API spins, burning CPU time
+
+Revision 1.9 2004/12/11 03:01:00 rpantos
+<rdar://problem/3907498> Java DNSRecord API should be cleaned up
+
+Revision 1.8 2004/11/30 23:51:05 cheshire
+Remove double semicolons
+
+Revision 1.7 2004/11/23 08:12:04 shersche
+Implement if_nametoindex and if_indextoname for Win32 platforms
+
+Revision 1.6 2004/11/23 03:41:14 cheshire
+Change JNISupport.c to call if_indextoname & if_nametoindex directly.
+(May require some additional glue code to work on Windows.)
+
+Revision 1.5 2004/11/17 17:07:44 cheshire
+Updated comment about AUTO_CALLBACKS
+
+Revision 1.4 2004/11/12 03:23:09 rpantos
+rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
+
+Revision 1.3 2004/06/18 04:44:17 rpantos
+Adapt to API unification on Windows
+
+Revision 1.2 2004/05/28 23:34:42 ksekar
+<rdar://problem/3672903>: Java project build errors
+
+Revision 1.1 2004/04/30 16:29:35 rpantos
+First checked in.
+
+
+ This file contains the platform support for DNSSD and related Java classes.
+ It is used to shim through to the underlying <dns_sd.h> API.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+// AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
+// callbacks automatically (as in the early Windows prototypes).
+// AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
+// invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.).
+// (Invoking callbacks automatically on a different thread sounds attractive, but while
+// the client gains by not needing to add an event source to its main event loop, it loses
+// by being forced to deal with concurrency and locking, which can be a bigger burden.)
+#ifndef AUTO_CALLBACKS
+#define AUTO_CALLBACKS 0
+#endif
+
+#if !AUTO_CALLBACKS
+#ifdef _WIN32
+#include <winsock2.h>
+#else //_WIN32
+#include <sys/types.h>
+#include <sys/select.h>
+#endif // _WIN32
+#endif // AUTO_CALLBACKS
+
+#include <dns_sd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <winsock2.h>
+#include <iphlpapi.h>
+static char * if_indextoname( DWORD ifIndex, char * nameBuff);
+static DWORD if_nametoindex( const char * nameStr );
+#define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
+#else // _WIN32
+#include <sys/socket.h>
+#include <net/if.h>
+#endif // _WIN32
+#include <jni.h>
+
+#include "DNSSD.java.h"
+
+//#include <syslog.h>
+
+// convenience definition
+#ifdef __GNUC__
+#define _UNUSED __attribute__ ((unused))
+#else
+#define _UNUSED
+#endif
+
+enum {
+ kInterfaceVersion = 1 // Must match version in .jar file
+};
+
+typedef struct OpContext OpContext;
+
+struct OpContext
+{
+ DNSServiceRef ServiceRef;
+ JNIEnv *Env;
+ jobject JavaObj;
+ jobject ClientObj;
+ jmethodID Callback;
+ jmethodID Callback2;
+};
+
+// For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
+#if AUTO_CALLBACKS
+JavaVM *gJavaVM = NULL;
+#endif
+
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
+ jint callerVersion)
+{
+ /* Ensure that caller & interface versions match. */
+ if ( callerVersion != kInterfaceVersion)
+ return kDNSServiceErr_Incompatible;
+
+#if AUTO_CALLBACKS
+ {
+ jsize numVMs;
+
+ if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
+ return kDNSServiceErr_BadState;
+ }
+#endif
+
+ // Set AppleDNSSD.hasAutoCallbacks
+ {
+#if AUTO_CALLBACKS
+ jboolean hasAutoC = JNI_TRUE;
+#else
+ jboolean hasAutoC = JNI_FALSE;
+#endif
+ jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
+ (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
+ }
+
+ return kDNSServiceErr_NoError;
+}
+
+
+static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str)
+// Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
+{
+ return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
+}
+
+static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
+// Wrapper for JNI GetStringUTFChars() that handles null str.
+{
+ if ( str != NULL)
+ (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
+}
+
+
+#if AUTO_CALLBACKS
+static void SetupCallbackState( JNIEnv **ppEnv)
+{
+ (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
+}
+
+static void TeardownCallbackState( void )
+{
+ (*gJavaVM)->DetachCurrentThread( gJavaVM);
+}
+
+#else // AUTO_CALLBACKS
+
+static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
+{
+ // No setup necessary if ProcessResults() has been called
+}
+
+static void TeardownCallbackState( void )
+{
+ // No teardown necessary if ProcessResults() has been called
+}
+#endif // AUTO_CALLBACKS
+
+
+static OpContext *NewContext( JNIEnv *pEnv, jobject owner,
+ const char *callbackName, const char *callbackSig)
+// Create and initialize a new OpContext.
+{
+ OpContext *pContext = (OpContext*) malloc( sizeof *pContext);
+
+ if ( pContext != NULL)
+ {
+ jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
+ "fListener", "Lcom/apple/dnssd/BaseListener;");
+
+ pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); // must convert local ref to global to cache;
+ pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField);
+ pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); // must convert local ref to global to cache
+ pContext->Callback = (*pEnv)->GetMethodID( pEnv,
+ (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
+ callbackName, callbackSig);
+ pContext->Callback2 = NULL; // not always used
+ }
+
+ return pContext;
+}
+
+
+static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
+// Invoke operationFailed() method on target with err.
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
+ jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
+ "(Lcom/apple/dnssd/DNSSDService;I)V");
+
+ (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
+}
+
+JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis)
+/* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+
+ if ( contextField != 0)
+ {
+ OpContext *pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
+ if ( pContext != NULL)
+ {
+ // MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate()
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, 0);
+ if ( pContext->ServiceRef != NULL)
+ DNSServiceRefDeallocate( pContext->ServiceRef);
+
+ (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
+ (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
+ free( pContext);
+ }
+ }
+}
+
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis)
+/* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
+{
+// BlockForData() not supported with AUTO_CALLBACKS
+#if !AUTO_CALLBACKS
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+
+ if ( contextField != 0)
+ {
+ OpContext *pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
+ if ( pContext != NULL)
+ {
+ fd_set readFDs;
+ int sd = DNSServiceRefSockFD( pContext->ServiceRef);
+ struct timeval timeout = { 1, 0 };
+ FD_ZERO( &readFDs);
+ FD_SET( sd, &readFDs);
+
+ // Q: Why do we poll here?
+ // A: Because there's no other thread-safe way to do it.
+ // Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not,
+ // and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>)
+ // The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while
+ // some other thread is monitoring that socket in select(), but the difficulty is that there's no general way
+ // to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously.
+ // If we try to do this without holding any lock, then right as we jump to the select() routine,
+ // some other thread could stop our operation (thereby closing the socket),
+ // and then that thread (or even some third, unrelated thread)
+ // could do some other DNS-SD operation (or some other operation that opens a new file descriptor)
+ // and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor
+ // that may coincidentally have the same numerical value, but is semantically unrelated
+ // to the true file descriptor we thought we were blocking on.
+ // We can't stop this race condition from happening, but at least if we wake up once a second we can detect
+ // when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd.
+
+ if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1);
+ }
+ }
+#endif // !AUTO_CALLBACKS
+ return(0);
+}
+
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
+/* Call through to DNSServiceProcessResult() while data remains on socket. */
+{
+#if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
+
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
+ DNSServiceErrorType err = kDNSServiceErr_BadState;
+
+ if ( pContext != NULL)
+ {
+ int sd = DNSServiceRefSockFD( pContext->ServiceRef);
+ fd_set readFDs;
+ struct timeval zeroTimeout = { 0, 0 };
+
+ pContext->Env = pEnv;
+
+ FD_ZERO( &readFDs);
+ FD_SET( sd, &readFDs);
+
+ err = kDNSServiceErr_NoError;
+ if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
+ {
+ err = DNSServiceProcessResult(pContext->ServiceRef);
+ // Use caution here!
+ // We cannot touch any data structures associated with this operation!
+ // The DNSServiceProcessResult() routine should have invoked our callback,
+ // and our callback could have terminated the operation with op.stop();
+ // and that means HaltOperation() will have been called, which frees pContext.
+ // Basically, from here we just have to get out without touching any stale
+ // data structures that could blow up on us! Particularly, any attempt
+ // to loop here reading more results from the file descriptor is unsafe.
+ }
+ }
+ return err;
+#endif // AUTO_CALLBACKS
+}
+
+
+static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
+ const char *replyDomain, void *context)
+{
+ OpContext *pContext = (OpContext*) context;
+
+ SetupCallbackState( &pContext->Env);
+
+ if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
+ {
+ if ( errorCode == kDNSServiceErr_NoError)
+ {
+ (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
+ ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
+ pContext->JavaObj, flags, interfaceIndex,
+ (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
+ (*pContext->Env)->NewStringUTF( pContext->Env, regtype),
+ (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
+ }
+ else
+ ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
+ }
+
+ TeardownCallbackState();
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
+ jint flags, jint ifIndex, jstring regType, jstring domain)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+ if ( contextField != 0)
+ pContext = NewContext( pEnv, pThis, "serviceFound",
+ "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ else
+ err = kDNSServiceErr_BadParam;
+
+ if ( pContext != NULL)
+ {
+ const char *regStr = SafeGetUTFChars( pEnv, regType);
+ const char *domainStr = SafeGetUTFChars( pEnv, domain);
+
+ pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
+ (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
+ "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+
+ err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
+ }
+
+ SafeReleaseUTFChars( pEnv, regType, regStr);
+ SafeReleaseUTFChars( pEnv, domain, domainStr);
+ }
+ else
+ err = kDNSServiceErr_NoMemory;
+
+ return err;
+}
+
+
+static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget,
+ uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context)
+{
+ OpContext *pContext = (OpContext*) context;
+ jclass txtCls;
+ jmethodID txtCtor;
+ jbyteArray txtBytes;
+ jobject txtObj;
+ jbyte *pBytes;
+
+ SetupCallbackState( &pContext->Env);
+
+ txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
+ txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
+
+ if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
+ NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
+ {
+ if ( errorCode == kDNSServiceErr_NoError)
+ {
+ // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
+ // pattern into a number here.
+ port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
+
+ // Initialize txtBytes with contents of txtRecord
+ pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL);
+ memcpy( pBytes, txtRecord, txtLen);
+ (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT);
+
+ // Construct txtObj with txtBytes
+ txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
+ (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
+
+ (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
+ pContext->JavaObj, flags, interfaceIndex,
+ (*pContext->Env)->NewStringUTF( pContext->Env, fullname),
+ (*pContext->Env)->NewStringUTF( pContext->Env, hosttarget),
+ port, txtObj);
+ }
+ else
+ ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
+ }
+
+ TeardownCallbackState();
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis,
+ jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+ if ( contextField != 0)
+ pContext = NewContext( pEnv, pThis, "serviceResolved",
+ "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
+ else
+ err = kDNSServiceErr_BadParam;
+
+ if ( pContext != NULL)
+ {
+ const char *servStr = SafeGetUTFChars( pEnv, serviceName);
+ const char *regStr = SafeGetUTFChars( pEnv, regType);
+ const char *domainStr = SafeGetUTFChars( pEnv, domain);
+
+ err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
+ servStr, regStr, domainStr, ServiceResolveReply, pContext);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
+ }
+
+ SafeReleaseUTFChars( pEnv, serviceName, servStr);
+ SafeReleaseUTFChars( pEnv, regType, regStr);
+ SafeReleaseUTFChars( pEnv, domain, domainStr);
+ }
+ else
+ err = kDNSServiceErr_NoMemory;
+
+ return err;
+}
+
+
+static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags,
+ DNSServiceErrorType errorCode, const char *serviceName,
+ const char *regType, const char *domain, void *context)
+{
+ OpContext *pContext = (OpContext*) context;
+
+ SetupCallbackState( &pContext->Env);
+
+ if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
+ {
+ if ( errorCode == kDNSServiceErr_NoError)
+ {
+ (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
+ pContext->JavaObj, flags,
+ (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
+ (*pContext->Env)->NewStringUTF( pContext->Env, regType),
+ (*pContext->Env)->NewStringUTF( pContext->Env, domain));
+ }
+ else
+ ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
+ }
+ TeardownCallbackState();
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv *pEnv, jobject pThis,
+ jint ifIndex, jint flags, jstring serviceName, jstring regType,
+ jstring domain, jstring host, jint port, jbyteArray txtRecord)
+{
+ //syslog(LOG_ERR, "BR");
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ jbyte *pBytes;
+ jsize numBytes;
+
+ //syslog(LOG_ERR, "BR: contextField %d", contextField);
+
+ if ( contextField != 0)
+ pContext = NewContext( pEnv, pThis, "serviceRegistered",
+ "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ else
+ err = kDNSServiceErr_BadParam;
+
+ if ( pContext != NULL)
+ {
+ const char *servStr = SafeGetUTFChars( pEnv, serviceName);
+ const char *regStr = SafeGetUTFChars( pEnv, regType);
+ const char *domainStr = SafeGetUTFChars( pEnv, domain);
+ const char *hostStr = SafeGetUTFChars( pEnv, host);
+
+ //syslog(LOG_ERR, "BR: regStr %s", regStr);
+
+ // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
+ // big-endian number into a 16-bit pattern here.
+ uint16_t portBits = port;
+ portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1];
+
+ pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
+ numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
+
+ err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
+ domainStr, hostStr, portBits,
+ numBytes, pBytes, ServiceRegisterReply, pContext);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
+ }
+
+ if ( pBytes != NULL)
+ (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
+
+ SafeReleaseUTFChars( pEnv, serviceName, servStr);
+ SafeReleaseUTFChars( pEnv, regType, regStr);
+ SafeReleaseUTFChars( pEnv, domain, domainStr);
+ SafeReleaseUTFChars( pEnv, host, hostStr);
+ }
+ else
+ err = kDNSServiceErr_NoMemory;
+
+ return err;
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis,
+ jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
+ jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ jbyte *pBytes;
+ jsize numBytes;
+ DNSRecordRef recRef;
+
+ if ( contextField != 0)
+ pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
+ if ( pContext == NULL || pContext->ServiceRef == NULL)
+ return kDNSServiceErr_BadParam;
+
+ pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
+ numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
+
+ err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, destObj, recField, (jlong) recRef);
+ }
+
+ if ( pBytes != NULL)
+ (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
+
+ return err;
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis,
+ jint flags, jbyteArray rData, jint ttl)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
+ jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ jbyte *pBytes;
+ jsize numBytes;
+ DNSRecordRef recRef = NULL;
+
+ if ( ownerField != 0)
+ {
+ jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
+ jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
+ if ( contextField != 0)
+ pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, ownerObj, contextField);
+ }
+ if ( recField != 0)
+ recRef = (DNSRecordRef) (*pEnv)->GetLongField( pEnv, pThis, recField);
+ if ( pContext == NULL || pContext->ServiceRef == NULL)
+ return kDNSServiceErr_BadParam;
+
+ pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
+ numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
+
+ err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
+
+ if ( pBytes != NULL)
+ (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
+
+ return err;
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
+ jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ DNSRecordRef recRef = NULL;
+
+ if ( ownerField != 0)
+ {
+ jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
+ jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
+ if ( contextField != 0)
+ pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, ownerObj, contextField);
+ }
+ if ( recField != 0)
+ recRef = (DNSRecordRef) (*pEnv)->GetLongField( pEnv, pThis, recField);
+ if ( pContext == NULL || pContext->ServiceRef == NULL)
+ return kDNSServiceErr_BadParam;
+
+ err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
+
+ return err;
+}
+
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+ if ( contextField != 0)
+ pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V");
+ else
+ err = kDNSServiceErr_BadParam;
+
+ if ( pContext != NULL)
+ {
+ err = DNSServiceCreateConnection( &pContext->ServiceRef);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
+ }
+ }
+ else
+ err = kDNSServiceErr_NoMemory;
+
+ return err;
+}
+
+struct RecordRegistrationRef
+{
+ OpContext *Context;
+ jobject RecordObj;
+};
+typedef struct RecordRegistrationRef RecordRegistrationRef;
+
+static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED,
+ DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags,
+ DNSServiceErrorType errorCode, void *context)
+{
+ RecordRegistrationRef *regEnvelope = (RecordRegistrationRef*) context;
+ OpContext *pContext = regEnvelope->Context;
+
+ SetupCallbackState( &pContext->Env);
+
+ if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
+ {
+ if ( errorCode == kDNSServiceErr_NoError)
+ {
+ (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
+ regEnvelope->RecordObj, flags);
+ }
+ else
+ ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
+ }
+
+ (*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj);
+ free( regEnvelope);
+
+ TeardownCallbackState();
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord( JNIEnv *pEnv, jobject pThis,
+ jint flags, jint ifIndex, jstring fullname, jint rrType, jint rrClass,
+ jbyteArray rData, jint ttl, jobject destObj)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
+ jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
+ const char *nameStr = SafeGetUTFChars( pEnv, fullname);
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ jbyte *pBytes;
+ jsize numBytes;
+ DNSRecordRef recRef;
+ RecordRegistrationRef *regEnvelope;
+
+ if ( contextField != 0)
+ pContext = (OpContext*) (*pEnv)->GetLongField( pEnv, pThis, contextField);
+ if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL)
+ return kDNSServiceErr_BadParam;
+
+ regEnvelope = calloc( 1, sizeof *regEnvelope);
+ if ( regEnvelope == NULL)
+ return kDNSServiceErr_NoMemory;
+ regEnvelope->Context = pContext;
+ regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache
+
+ pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
+ numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
+
+ err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex,
+ nameStr, rrType, rrClass, numBytes, pBytes, ttl,
+ RegisterRecordReply, regEnvelope);
+
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, destObj, recField, (jlong) recRef);
+ }
+ else
+ {
+ if ( regEnvelope->RecordObj != NULL)
+ (*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj);
+ free( regEnvelope);
+ }
+
+ if ( pBytes != NULL)
+ (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
+
+ SafeReleaseUTFChars( pEnv, fullname, nameStr);
+
+ return err;
+}
+
+
+static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *serviceName,
+ uint16_t rrtype, uint16_t rrclass, uint16_t rdlen,
+ const void *rdata, uint32_t ttl, void *context)
+{
+ OpContext *pContext = (OpContext*) context;
+ jbyteArray rDataObj;
+ jbyte *pBytes;
+
+ SetupCallbackState( &pContext->Env);
+
+ if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
+ NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
+ {
+ if ( errorCode == kDNSServiceErr_NoError)
+ {
+ // Initialize rDataObj with contents of rdata
+ pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL);
+ memcpy( pBytes, rdata, rdlen);
+ (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT);
+
+ (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
+ pContext->JavaObj, flags, interfaceIndex,
+ (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
+ rrtype, rrclass, rDataObj, ttl);
+ }
+ else
+ ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
+ }
+ TeardownCallbackState();
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis,
+ jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+ if ( contextField != 0)
+ pContext = NewContext( pEnv, pThis, "queryAnswered",
+ "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
+ else
+ err = kDNSServiceErr_BadParam;
+
+ if ( pContext != NULL)
+ {
+ const char *servStr = SafeGetUTFChars( pEnv, serviceName);
+
+ err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
+ rrtype, rrclass, ServiceQueryReply, pContext);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
+ }
+
+ SafeReleaseUTFChars( pEnv, serviceName, servStr);
+ }
+ else
+ err = kDNSServiceErr_NoMemory;
+
+ return err;
+}
+
+
+static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char *replyDomain, void *context)
+{
+ OpContext *pContext = (OpContext*) context;
+
+ SetupCallbackState( &pContext->Env);
+
+ if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
+ {
+ if ( errorCode == kDNSServiceErr_NoError)
+ {
+ (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
+ ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
+ pContext->JavaObj, flags, interfaceIndex,
+ (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
+ }
+ else
+ ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
+ }
+ TeardownCallbackState();
+}
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
+ jint flags, jint ifIndex)
+{
+ jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
+ jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
+ OpContext *pContext = NULL;
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+ if ( contextField != 0)
+ pContext = NewContext( pEnv, pThis, "domainFound",
+ "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
+ else
+ err = kDNSServiceErr_BadParam;
+
+ if ( pContext != NULL)
+ {
+ pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
+ (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
+ "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
+
+ err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
+ DomainEnumReply, pContext);
+ if ( err == kDNSServiceErr_NoError)
+ {
+ (*pEnv)->SetLongField( pEnv, pThis, contextField, (jlong) pContext);
+ }
+ }
+ else
+ err = kDNSServiceErr_NoMemory;
+
+ return err;
+}
+
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
+ jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
+{
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ const char *nameStr = SafeGetUTFChars( pEnv, serviceName);
+ const char *regStr = SafeGetUTFChars( pEnv, regtype);
+ const char *domStr = SafeGetUTFChars( pEnv, domain);
+ char buff[ kDNSServiceMaxDomainName + 1];
+
+ err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
+
+ if ( err == kDNSServiceErr_NoError)
+ {
+ // pOut is expected to be a String[1] array.
+ (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
+ }
+
+ SafeReleaseUTFChars( pEnv, serviceName, nameStr);
+ SafeReleaseUTFChars( pEnv, regtype, regStr);
+ SafeReleaseUTFChars( pEnv, domain, domStr);
+
+ return err;
+}
+
+JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED,
+ jint flags, jint ifIndex, jstring fullName,
+ jint rrtype, jint rrclass, jbyteArray rdata)
+{
+ jbyte *pBytes;
+ jsize numBytes;
+ const char *nameStr = SafeGetUTFChars( pEnv, fullName);
+
+ pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
+ numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
+
+ DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
+
+ if ( pBytes != NULL)
+ (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
+
+ SafeReleaseUTFChars( pEnv, fullName, nameStr);
+}
+
+#define LOCAL_ONLY_NAME "loo"
+
+JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
+ jint ifIndex)
+{
+ char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
+
+ if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
+ p = if_indextoname( ifIndex, nameBuff );
+
+ return (*pEnv)->NewStringUTF( pEnv, p);
+}
+
+
+JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED,
+ jstring ifName)
+{
+ uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
+ const char *nameStr = SafeGetUTFChars( pEnv, ifName);
+
+ if (strcmp(nameStr, LOCAL_ONLY_NAME))
+ ifIndex = if_nametoindex( nameStr);
+
+ SafeReleaseUTFChars( pEnv, ifName, nameStr);
+
+ return ifIndex;
+}
+
+
+#if defined(_WIN32)
+static char*
+if_indextoname( DWORD ifIndex, char * nameBuff)
+{
+ PIP_ADAPTER_INFO pAdapterInfo = NULL;
+ PIP_ADAPTER_INFO pAdapter = NULL;
+ DWORD dwRetVal = 0;
+ char * ifName = NULL;
+ ULONG ulOutBufLen = 0;
+
+ if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
+ {
+ goto exit;
+ }
+
+ pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
+
+ if (pAdapterInfo == NULL)
+ {
+ goto exit;
+ }
+
+ dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
+
+ if (dwRetVal != NO_ERROR)
+ {
+ goto exit;
+ }
+
+ pAdapter = pAdapterInfo;
+ while (pAdapter)
+ {
+ if (pAdapter->Index == ifIndex)
+ {
+ // It would be better if we passed in the length of nameBuff to this
+ // function, so we would have absolute certainty that no buffer
+ // overflows would occur. Buffer overflows *shouldn't* occur because
+ // nameBuff is of size MAX_ADAPTER_NAME_LENGTH.
+ strcpy( nameBuff, pAdapter->AdapterName );
+ ifName = nameBuff;
+ break;
+ }
+
+ pAdapter = pAdapter->Next;
+ }
+
+exit:
+
+ if (pAdapterInfo != NULL)
+ {
+ free( pAdapterInfo );
+ pAdapterInfo = NULL;
+ }
+
+ return ifName;
+}
+
+
+static DWORD
+if_nametoindex( const char * nameStr )
+{
+ PIP_ADAPTER_INFO pAdapterInfo = NULL;
+ PIP_ADAPTER_INFO pAdapter = NULL;
+ DWORD dwRetVal = 0;
+ DWORD ifIndex = 0;
+ ULONG ulOutBufLen = 0;
+
+ if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
+ {
+ goto exit;
+ }
+
+ pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
+
+ if (pAdapterInfo == NULL)
+ {
+ goto exit;
+ }
+
+ dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
+
+ if (dwRetVal != NO_ERROR)
+ {
+ goto exit;
+ }
+
+ pAdapter = pAdapterInfo;
+ while (pAdapter)
+ {
+ if (strcmp(pAdapter->AdapterName, nameStr) == 0)
+ {
+ ifIndex = pAdapter->Index;
+ break;
+ }
+
+ pAdapter = pAdapter->Next;
+ }
+
+exit:
+
+ if (pAdapterInfo != NULL)
+ {
+ free( pAdapterInfo );
+ pAdapterInfo = NULL;
+ }
+
+ return ifIndex;
+}
+#endif
diff --git a/usr/src/lib/libdns_sd/java/common/mapfile-vers b/usr/src/lib/libdns_sd/java/common/mapfile-vers
new file mode 100644
index 0000000000..0ae50ad6ff
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/common/mapfile-vers
@@ -0,0 +1,48 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUNW_1.1 {
+ global:
+ Java_com_apple_dnssd_AppleBrowser_CreateBrowser;
+ Java_com_apple_dnssd_AppleDNSRecord_Remove;
+ Java_com_apple_dnssd_AppleDNSRecord_Update;
+ Java_com_apple_dnssd_AppleDNSSD_ConstructName;
+ Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName;
+ Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex;
+ Java_com_apple_dnssd_AppleDNSSD_InitLibrary;
+ Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord;
+ Java_com_apple_dnssd_AppleDomainEnum_BeginEnum;
+ Java_com_apple_dnssd_AppleQuery_CreateQuery;
+ Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection;
+ Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord;
+ Java_com_apple_dnssd_AppleRegistration_AddRecord;
+ Java_com_apple_dnssd_AppleRegistration_BeginRegister;
+ Java_com_apple_dnssd_AppleResolver_CreateResolver;
+ Java_com_apple_dnssd_AppleService_BlockForData;
+ Java_com_apple_dnssd_AppleService_HaltOperation;
+ Java_com_apple_dnssd_AppleService_ProcessResults;
+ local:
+ *;
+};
diff --git a/usr/src/lib/libdns_sd/java/i386/Makefile b/usr/src/lib/libdns_sd/java/i386/Makefile
new file mode 100644
index 0000000000..3b6c2a1943
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/i386/Makefile
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+CPPFLAGS += -_gcc=-Wno-pointer-to-int-cast -_gcc=-Wno-int-to-pointer-cast
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/libdns_sd/java/sparc/Makefile b/usr/src/lib/libdns_sd/java/sparc/Makefile
new file mode 100644
index 0000000000..3b6c2a1943
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/sparc/Makefile
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+CPPFLAGS += -_gcc=-Wno-pointer-to-int-cast -_gcc=-Wno-int-to-pointer-cast
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/libdns_sd/java/sparcv9/Makefile b/usr/src/lib/libdns_sd/java/sparcv9/Makefile
new file mode 100644
index 0000000000..b645e1caed
--- /dev/null
+++ b/usr/src/lib/libdns_sd/java/sparcv9/Makefile
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libdns_sd/sparc/Makefile b/usr/src/lib/libdns_sd/sparc/Makefile
new file mode 100644
index 0000000000..9c1be5bf3a
--- /dev/null
+++ b/usr/src/lib/libdns_sd/sparc/Makefile
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libdns_sd/sparcv9/Makefile b/usr/src/lib/libdns_sd/sparcv9/Makefile
new file mode 100644
index 0000000000..abae92c693
--- /dev/null
+++ b/usr/src/lib/libdns_sd/sparcv9/Makefile
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+CFLAGS64 += -erroff=E_ASSIGNMENT_TYPE_MISMATCH
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)