2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
26 Revision 1.4 2004/12/11 03:00:59 rpantos
27 <rdar://problem/3907498> Java DNSRecord API should be cleaned up
29 Revision 1.3 2004/11/12 03:23:08 rpantos
30 rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex.
32 Revision 1.2 2004/05/20 17:43:18 cheshire
33 Fix invalid UTF-8 characters in file
35 Revision 1.1 2004/04/30 16:32:34 rpantos
39 This file declares and implements DNSSD, the central Java factory class
40 for doing DNS Service Discovery. It includes the mostly-abstract public
41 interface, as well as the Apple* implementation subclasses.
44 - implement network interface mappings
49 package com
.apple
.dnssd
;
53 DNSSD provides access to DNS Service Discovery features of ZeroConf networking.<P>
55 It is a factory class that is used to invoke registration and discovery-related
56 operations. Most operations are non-blocking; clients are called back through an interface
57 with the result of an operation. Callbacks are made from a separate worker thread.<P>
59 For example, in this program<P>
61 class MyClient implements BrowseListener {
62 void lookForWebServers() {
63 myBrowser = DNSSD.browse("_http_.tcp", this);
66 public void serviceFound(DNSSDService browser, int flags, int ifIndex,
67 String serviceName, String regType, String domain) {}
70 <CODE>MyClient.serviceFound()</CODE> would be called for every HTTP server discovered in the
71 default browse domain(s).
74 abstract public class DNSSD
76 /** Flag indicates to a {@link BrowseListener} that another result is
77 queued. Applications should not update their UI to display browse
78 results if the MORE_COMING flag is set; they will be called at least once
79 more with the flag clear.
81 public static final int MORE_COMING
= ( 1 << 0 );
83 /** If flag is set in a {@link DomainListener} callback, indicates that the result is the default domain. */
84 public static final int DEFAULT
= ( 1 << 2 );
86 /** If flag is set, a name conflict will trigger an exception when registering non-shared records.<P>
87 A name must be explicitly specified when registering a service if this bit is set
88 (i.e. the default name may not not be used).
90 public static final int NO_AUTO_RENAME
= ( 1 << 3 );
92 /** If flag is set, allow multiple records with this name on the network (e.g. PTR records)
93 when registering individual records on a {@link DNSSDRegistration}.
95 public static final int SHARED
= ( 1 << 4 );
97 /** If flag is set, records with this name must be unique on the network (e.g. SRV records). */
98 public static final int UNIQUE
= ( 1 << 5 );
100 /** Set flag when calling enumerateDomains() to restrict results to domains recommended for browsing. */
101 public static final int BROWSE_DOMAINS
= ( 1 << 6 );
102 /** Set flag when calling enumerateDomains() to restrict results to domains recommended for registration. */
103 public static final int REGISTRATION_DOMAINS
= ( 1 << 7 );
105 /** Maximum length, in bytes, of a domain name represented as an escaped C-String. */
106 public static final int MAX_DOMAIN_NAME
= 1005;
108 /** Pass for ifIndex to specify all available interfaces. */
109 public static final int ALL_INTERFACES
= 0;
111 /** Pass for ifIndex to specify the localhost interface. */
112 public static final int LOCALHOST_ONLY
= -1;
114 /** Browse for instances of a service.<P>
116 Note: browsing consumes network bandwidth. Call {@link DNSSDService#stop} when you have finished browsing.<P>
119 Currently ignored, reserved for future use.
122 If non-zero, specifies the interface on which to browse for services
123 (the index for a given interface is determined via the if_nametoindex()
124 family of calls.) Most applications will pass 0 to browse on all available
125 interfaces. Pass -1 to only browse for services provided on the local host.
128 The registration type being browsed for followed by the protocol, separated by a
129 dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
132 If non-null, specifies the domain on which to browse for services.
133 Most applications will not specify a domain, instead browsing on the
137 This object will get called when instances of the service are discovered (or disappear).
139 @return A {@link DNSSDService} that represents the active browse operation.
141 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
142 @see RuntimePermission
144 public static DNSSDService
browse( int flags
, int ifIndex
, String regType
, String domain
, BrowseListener listener
)
145 throws DNSSDException
146 { return getInstance()._makeBrowser( flags
, ifIndex
, regType
, domain
, listener
); }
148 /** Browse for instances of a service. Use default flags, ifIndex and domain.<P>
151 The registration type being browsed for followed by the protocol, separated by a
152 dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
155 This object will get called when instances of the service are discovered (or disappear).
157 @return A {@link DNSSDService} that represents the active browse operation.
159 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
160 @see RuntimePermission
162 public static DNSSDService
browse( String regType
, BrowseListener listener
)
163 throws DNSSDException
164 { return browse( 0, 0, regType
, "", listener
); }
166 /** Resolve a service name discovered via browse() to a target host name, port number, and txt record.<P>
168 Note: Applications should NOT use resolve() solely for txt record monitoring - use
169 queryRecord() instead, as it is more efficient for this task.<P>
171 Note: When the desired results have been returned, the client MUST terminate the resolve by
172 calling {@link DNSSDService#stop}.<P>
174 Note: resolve() behaves correctly for typical services that have a single SRV record and
175 a single TXT record (the TXT record may be empty.) To resolve non-standard services with
176 multiple SRV or TXT records, use queryRecord().<P>
179 Currently ignored, reserved for future use.
182 The interface on which to resolve the service. The client should
183 pass the interface on which the serviceName was discovered (i.e.
184 the ifIndex passed to the serviceFound() callback)
185 or 0 to resolve the named service on all available interfaces.
188 The servicename to be resolved.
191 The registration type being resolved followed by the protocol, separated by a
192 dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
195 The domain on which the service is registered, i.e. the domain passed
196 to the serviceFound() callback.
199 This object will get called when the service is resolved.
201 @return A {@link DNSSDService} that represents the active resolve operation.
203 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
204 @see RuntimePermission
206 public static DNSSDService
resolve( int flags
, int ifIndex
, String serviceName
, String regType
,
207 String domain
, ResolveListener listener
)
208 throws DNSSDException
209 { return getInstance()._resolve( flags
, ifIndex
, serviceName
, regType
, domain
, listener
); }
211 /** Register a service, to be discovered via browse() and resolve() calls.<P>
213 Possible values are: NO_AUTO_RENAME.
216 If non-zero, specifies the interface on which to register the service
217 (the index for a given interface is determined via the if_nametoindex()
218 family of calls.) Most applications will pass 0 to register on all
219 available interfaces. Pass -1 to register a service only on the local
220 machine (service will not be visible to remote hosts).
223 If non-null, specifies the service name to be registered.
224 Applications need not specify a name, in which case the
225 computer name is used (this name is communicated to the client via
226 the serviceRegistered() callback).
229 The registration type being registered followed by the protocol, separated by a
230 dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
233 If non-null, specifies the domain on which to advertise the service.
234 Most applications will not specify a domain, instead automatically
235 registering in the default domain(s).
238 If non-null, specifies the SRV target host name. Most applications
239 will not specify a host, instead automatically using the machine's
240 default host name(s). Note that specifying a non-null host does NOT
241 create an address record for that host - the application is responsible
242 for ensuring that the appropriate address record exists, or creating it
243 via {@link DNSSDRegistration#addRecord}.
246 The port on which the service accepts connections. Pass 0 for a
247 "placeholder" service (i.e. a service that will not be discovered by
248 browsing, but will cause a name conflict if another client tries to
249 register that same name.) Most clients will not use placeholder services.
252 The txt record rdata. May be null. Note that a non-null txtRecord
253 MUST be a properly formatted DNS TXT record, i.e. <length byte> <data>
254 <length byte> <data> ...
257 This object will get called when the service is registered.
259 @return A {@link DNSSDRegistration} that controls the active registration.
261 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
262 @see RuntimePermission
264 public static DNSSDRegistration
register( int flags
, int ifIndex
, String serviceName
, String regType
,
265 String domain
, String host
, int port
, TXTRecord txtRecord
, RegisterListener listener
)
266 throws DNSSDException
267 { return getInstance()._register( flags
, ifIndex
, serviceName
, regType
, domain
, host
, port
, txtRecord
, listener
); }
269 /** Register a service, to be discovered via browse() and resolve() calls. Use default flags, ifIndex, domain, host and txtRecord.<P>
271 If non-null, specifies the service name to be registered.
272 Applications need not specify a name, in which case the
273 computer name is used (this name is communicated to the client via
274 the serviceRegistered() callback).
277 The registration type being registered followed by the protocol, separated by a
278 dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
281 The port on which the service accepts connections. Pass 0 for a
282 "placeholder" service (i.e. a service that will not be discovered by
283 browsing, but will cause a name conflict if another client tries to
284 register that same name.) Most clients will not use placeholder services.
287 This object will get called when the service is registered.
289 @return A {@link DNSSDRegistration} that controls the active registration.
291 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
292 @see RuntimePermission
294 public static DNSSDRegistration
register( String serviceName
, String regType
, int port
, RegisterListener listener
)
295 throws DNSSDException
296 { return register( 0, 0, serviceName
, regType
, null, null, port
, null, listener
); }
298 /** Query for an arbitrary DNS record.<P>
300 Possible values are: MORE_COMING.
303 If non-zero, specifies the interface on which to issue the query
304 (the index for a given interface is determined via the if_nametoindex()
305 family of calls.) Passing 0 causes the name to be queried for on all
306 interfaces. Passing -1 causes the name to be queried for only on the
310 The full domain name of the resource record to be queried for.
313 The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc)
314 as defined in nameser.h.
317 The class of the resource record, as defined in nameser.h
318 (usually 1 for the Internet class).
321 This object will get called when the query completes.
323 @return A {@link DNSSDService} that controls the active query.
325 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
326 @see RuntimePermission
328 public static DNSSDService
queryRecord( int flags
, int ifIndex
, String serviceName
, int rrtype
,
329 int rrclass
, QueryListener listener
)
330 throws DNSSDException
331 { return getInstance()._queryRecord( flags
, ifIndex
, serviceName
, rrtype
, rrclass
, listener
); }
333 /** Asynchronously enumerate domains available for browsing and registration.<P>
335 Currently, the only domain returned is "local.", but other domains will be returned in future.<P>
337 The enumeration MUST be cancelled by calling {@link DNSSDService#stop} when no more domains
340 Possible values are: BROWSE_DOMAINS, REGISTRATION_DOMAINS.
343 If non-zero, specifies the interface on which to look for domains.
344 (the index for a given interface is determined via the if_nametoindex()
345 family of calls.) Most applications will pass 0 to enumerate domains on
349 This object will get called when domains are found.
351 @return A {@link DNSSDService} that controls the active enumeration.
353 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
354 @see RuntimePermission
356 public static DNSSDService
enumerateDomains( int flags
, int ifIndex
, DomainListener listener
)
357 throws DNSSDException
358 { return getInstance()._enumerateDomains( flags
, ifIndex
, listener
); }
360 /** Concatenate a three-part domain name (as provided to the listeners) into a
361 properly-escaped full domain name. Note that strings passed to listeners are
362 ALREADY ESCAPED where necessary.<P>
364 The service name - any dots or slashes must NOT be escaped.
365 May be null (to construct a PTR record name, e.g. "_ftp._tcp.apple.com").
368 The registration type followed by the protocol, separated by a dot (e.g. "_ftp._tcp").
371 The domain name, e.g. "apple.com". Any literal dots or backslashes must be escaped.
373 @return The full domain name.
375 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
376 @see RuntimePermission
378 public static String
constructFullName( String serviceName
, String regType
, String domain
)
379 throws DNSSDException
380 { return getInstance()._constructFullName( serviceName
, regType
, domain
); }
382 /** Instruct the daemon to verify the validity of a resource record that appears to
383 be out of date. (e.g. because tcp connection to a service's target failed.) <P>
385 Causes the record to be flushed from the daemon's cache (as well as all other
386 daemons' caches on the network) if the record is determined to be invalid.<P>
388 Currently unused, reserved for future use.
391 If non-zero, specifies the interface on which to reconfirm the record
392 (the index for a given interface is determined via the if_nametoindex()
393 family of calls.) Passing 0 causes the name to be reconfirmed on all
394 interfaces. Passing -1 causes the name to be reconfirmed only on the
398 The resource record's full domain name.
401 The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h.
404 The class of the resource record, as defined in nameser.h (usually 1).
407 The raw rdata of the resource record.
409 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
410 @see RuntimePermission
412 public static void reconfirmRecord( int flags
, int ifIndex
, String fullName
, int rrtype
,
413 int rrclass
, byte[] rdata
)
414 { getInstance()._reconfirmRecord( flags
, ifIndex
, fullName
, rrtype
, rrclass
, rdata
); }
416 /** Return the canonical name of a particular interface index.<P>
418 A valid interface index. Must not be ALL_INTERFACES.
420 @return The name of the interface, which should match java.net.NetworkInterface.getName().
422 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
423 @see RuntimePermission
425 public static String
getNameForIfIndex( int ifIndex
)
426 { return getInstance()._getNameForIfIndex( ifIndex
); }
428 /** Return the index of a named interface.<P>
430 A valid interface name. An example is java.net.NetworkInterface.getName().
432 @return The interface index.
434 @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>.
435 @see RuntimePermission
437 public static int getIfIndexForName( String ifName
)
438 { return getInstance()._getIfIndexForName( ifName
); }
440 protected DNSSD() {} // prevent direct instantiation
442 /** Return the single instance of DNSSD. */
443 static protected final DNSSD
getInstance()
445 SecurityManager sm
= System
.getSecurityManager();
447 sm
.checkPermission( new RuntimePermission( "getDNSSDInstance"));
451 abstract protected DNSSDService
_makeBrowser( int flags
, int ifIndex
, String regType
, String domain
, BrowseListener listener
)
452 throws DNSSDException
;
454 abstract protected DNSSDService
_resolve( int flags
, int ifIndex
, String serviceName
, String regType
,
455 String domain
, ResolveListener listener
)
456 throws DNSSDException
;
458 abstract protected DNSSDRegistration
_register( int flags
, int ifIndex
, String serviceName
, String regType
,
459 String domain
, String host
, int port
, TXTRecord txtRecord
, RegisterListener listener
)
460 throws DNSSDException
;
462 abstract protected DNSSDService
_queryRecord( int flags
, int ifIndex
, String serviceName
, int rrtype
,
463 int rrclass
, QueryListener listener
)
464 throws DNSSDException
;
466 abstract protected DNSSDService
_enumerateDomains( int flags
, int ifIndex
, DomainListener listener
)
467 throws DNSSDException
;
469 abstract protected String
_constructFullName( String serviceName
, String regType
, String domain
)
470 throws DNSSDException
;
472 abstract protected void _reconfirmRecord( int flags
, int ifIndex
, String fullName
, int rrtype
,
473 int rrclass
, byte[] rdata
);
475 abstract protected String
_getNameForIfIndex( int ifIndex
);
477 abstract protected int _getIfIndexForName( String ifName
);
479 protected static DNSSD fInstance
;
485 String name
= System
.getProperty( "com.apple.dnssd.DNSSD" );
487 name
= "com.apple.dnssd.AppleDNSSD"; // Fall back to Apple-provided class.
488 fInstance
= (DNSSD
) Class
.forName( name
).newInstance();
492 throw new InternalError( "cannot instantiate DNSSD" + e
);
498 // Concrete implementation of DNSSDException
499 class AppleDNSSDException
extends DNSSDException
501 public AppleDNSSDException( int errorCode
) { fErrorCode
= errorCode
; }
503 public int getErrorCode() { return fErrorCode
; }
505 public String
getMessage()
507 final String kMessages
[] = { // should probably be put into a resource or something
517 "", // there is NO number 6
518 "ALREADY_REGISTERED",
523 "BAD_INTERFACE_INDEX"
526 if ( fErrorCode
<= UNKNOWN
&& fErrorCode
> ( UNKNOWN
- kMessages
.length
))
528 return "DNS-SD Error " + String
.valueOf( fErrorCode
) + ": " + kMessages
[ UNKNOWN
- fErrorCode
];
531 return super.getMessage() + "(" + String
.valueOf( fErrorCode
) + ")";
534 protected int fErrorCode
;
537 // The concrete, default implementation.
538 class AppleDNSSD
extends DNSSD
542 System
.loadLibrary( "jdns_sd");
544 int libInitResult
= InitLibrary( 1);
546 if ( libInitResult
!= DNSSDException
.NO_ERROR
)
547 throw new InternalError( "cannot instantiate DNSSD: " + new AppleDNSSDException( libInitResult
).getMessage());
550 static public boolean hasAutoCallbacks
; // Set by InitLibrary() to value of AUTO_CALLBACKS
552 protected DNSSDService
_makeBrowser( int flags
, int ifIndex
, String regType
, String domain
, BrowseListener client
)
553 throws DNSSDException
555 return new AppleBrowser( flags
, ifIndex
, regType
, domain
, client
);
558 protected DNSSDService
_resolve( int flags
, int ifIndex
, String serviceName
, String regType
,
559 String domain
, ResolveListener client
)
560 throws DNSSDException
562 return new AppleResolver( flags
, ifIndex
, serviceName
, regType
, domain
, client
);
565 protected DNSSDRegistration
_register( int flags
, int ifIndex
, String serviceName
, String regType
,
566 String domain
, String host
, int port
, TXTRecord txtRecord
, RegisterListener client
)
567 throws DNSSDException
569 return new AppleRegistration( flags
, ifIndex
, serviceName
, regType
, domain
, host
, port
,
570 ( txtRecord
!= null) ? txtRecord
.getRawBytes() : null, client
);
573 protected DNSSDService
_queryRecord( int flags
, int ifIndex
, String serviceName
, int rrtype
,
574 int rrclass
, QueryListener client
)
575 throws DNSSDException
577 return new AppleQuery( flags
, ifIndex
, serviceName
, rrtype
, rrclass
, client
);
580 protected DNSSDService
_enumerateDomains( int flags
, int ifIndex
, DomainListener listener
)
581 throws DNSSDException
583 return new AppleDomainEnum( flags
, ifIndex
, listener
);
586 protected String
_constructFullName( String serviceName
, String regType
, String domain
)
587 throws DNSSDException
589 String
[] responseHolder
= new String
[1]; // lame maneuver to get around Java's lack of reference parameters
591 int rc
= ConstructName( serviceName
, regType
, domain
, responseHolder
);
593 throw new AppleDNSSDException( rc
);
595 return responseHolder
[0];
598 protected void _reconfirmRecord( int flags
, int ifIndex
, String fullName
, int rrtype
,
599 int rrclass
, byte[] rdata
)
601 ReconfirmRecord( flags
, ifIndex
, fullName
, rrtype
, rrclass
, rdata
);
604 protected String
_getNameForIfIndex( int ifIndex
)
606 return GetNameForIfIndex( ifIndex
);
609 protected int _getIfIndexForName( String ifName
)
611 return GetIfIndexForName( ifName
);
615 protected native int ConstructName( String serviceName
, String regType
, String domain
, String
[] pOut
);
617 protected native void ReconfirmRecord( int flags
, int ifIndex
, String fullName
, int rrtype
,
618 int rrclass
, byte[] rdata
);
620 protected native String
GetNameForIfIndex( int ifIndex
);
622 protected native int GetIfIndexForName( String ifName
);
624 protected static native int InitLibrary( int callerVersion
);
627 class AppleService
implements DNSSDService
, Runnable
629 public AppleService() { fNativeContext
= 0; }
631 public void stop() { this.HaltOperation(); }
633 public void finalize() throws Throwable
639 /* The run() method is used internally to schedule an update from another thread */
642 this.ProcessResults();
645 /* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */
646 protected native int BlockForData( int msTimeout
);
648 /* Call ProcessResults when data appears on socket descriptor. */
649 protected native void ProcessResults();
651 protected native void HaltOperation();
653 protected void ThrowOnErr( int rc
) throws DNSSDException
656 throw new AppleDNSSDException( rc
);
659 protected int /* warning */ fNativeContext
; // Private storage for native side
663 // A ServiceThread calls AppleService.BlockForData() and schedules its client
664 // when data appears.
665 class ServiceThread
extends Thread
667 public ServiceThread( AppleService owner
) { fOwner
= owner
; }
675 result
= fOwner
.BlockForData( -1);
681 break; // terminate thread
685 protected AppleService fOwner
;
689 class AppleBrowser
extends AppleService
691 public AppleBrowser( int flags
, int ifIndex
, String regType
, String domain
, BrowseListener client
)
692 throws DNSSDException
695 this.ThrowOnErr( this.CreateBrowser( flags
, ifIndex
, regType
, domain
));
696 if ( !AppleDNSSD
.hasAutoCallbacks
)
697 new ServiceThread( this).start();
700 // Sets fNativeContext. Returns non-zero on error.
701 protected native int CreateBrowser( int flags
, int ifIndex
, String regType
, String domain
);
703 protected BrowseListener fClient
;
706 class AppleResolver
extends AppleService
708 public AppleResolver( int flags
, int ifIndex
, String serviceName
, String regType
,
709 String domain
, ResolveListener client
)
710 throws DNSSDException
713 this.ThrowOnErr( this.CreateResolver( flags
, ifIndex
, serviceName
, regType
, domain
));
714 if ( !AppleDNSSD
.hasAutoCallbacks
)
715 new ServiceThread( this).start();
718 // Sets fNativeContext. Returns non-zero on error.
719 protected native int CreateResolver( int flags
, int ifIndex
, String serviceName
, String regType
,
722 protected ResolveListener fClient
;
725 // An AppleDNSRecord is a simple wrapper around a dns_sd DNSRecord.
726 class AppleDNSRecord
implements DNSRecord
728 public AppleDNSRecord( AppleService owner
)
731 fRecord
= 0; // record always starts out empty
734 public void update( int flags
, byte[] rData
, int ttl
)
735 throws DNSSDException
737 this.ThrowOnErr( this.Update( flags
, rData
, ttl
));
741 throws DNSSDException
743 this.ThrowOnErr( this.Remove());
746 protected int fRecord
; // Really a DNSRecord; sizeof(int) == sizeof(void*) ?
747 protected AppleService fOwner
;
749 protected void ThrowOnErr( int rc
) throws DNSSDException
752 throw new AppleDNSSDException( rc
);
755 protected native int Update( int flags
, byte[] rData
, int ttl
);
757 protected native int Remove();
760 class AppleRegistration
extends AppleService
implements DNSSDRegistration
762 public AppleRegistration( int flags
, int ifIndex
, String serviceName
, String regType
, String domain
,
763 String host
, int port
, byte[] txtRecord
, RegisterListener client
)
764 throws DNSSDException
767 this.ThrowOnErr( this.BeginRegister( ifIndex
, flags
, serviceName
, regType
, domain
, host
, port
, txtRecord
));
768 if ( !AppleDNSSD
.hasAutoCallbacks
)
769 new ServiceThread( this).start();
772 public DNSRecord
addRecord( int flags
, int rrType
, byte[] rData
, int ttl
)
773 throws DNSSDException
775 AppleDNSRecord newRecord
= new AppleDNSRecord( this);
777 this.ThrowOnErr( this.AddRecord( flags
, rrType
, rData
, ttl
, newRecord
));
782 public DNSRecord
getTXTRecord()
783 throws DNSSDException
785 return new AppleDNSRecord( this); // A record with ref 0 is understood to be primary TXT record
788 // Sets fNativeContext. Returns non-zero on error.
789 protected native int BeginRegister( int ifIndex
, int flags
, String serviceName
, String regType
,
790 String domain
, String host
, int port
, byte[] txtRecord
);
792 // Sets fNativeContext. Returns non-zero on error.
793 protected native int AddRecord( int flags
, int rrType
, byte[] rData
, int ttl
, AppleDNSRecord destObj
);
795 protected RegisterListener fClient
;
798 class AppleQuery
extends AppleService
800 public AppleQuery( int flags
, int ifIndex
, String serviceName
, int rrtype
,
801 int rrclass
, QueryListener client
)
802 throws DNSSDException
805 this.ThrowOnErr( this.CreateQuery( flags
, ifIndex
, serviceName
, rrtype
, rrclass
));
806 if ( !AppleDNSSD
.hasAutoCallbacks
)
807 new ServiceThread( this).start();
810 // Sets fNativeContext. Returns non-zero on error.
811 protected native int CreateQuery( int flags
, int ifIndex
, String serviceName
, int rrtype
, int rrclass
);
813 protected QueryListener fClient
;
816 class AppleDomainEnum
extends AppleService
818 public AppleDomainEnum( int flags
, int ifIndex
, DomainListener listener
)
819 throws DNSSDException
822 this.ThrowOnErr( this.BeginEnum( flags
, ifIndex
));
823 if ( !AppleDNSSD
.hasAutoCallbacks
)
824 new ServiceThread( this).start();
827 // Sets fNativeContext. Returns non-zero on error.
828 protected native int BeginEnum( int flags
, int ifIndex
);
830 protected DomainListener fClient
;