1################################################################################
2#
3# Copyright (c) 2007-2008 Christopher J. Stawarz
4#
5# Permission is hereby granted, free of charge, to any person
6# obtaining a copy of this software and associated documentation files
7# (the "Software"), to deal in the Software without restriction,
8# including without limitation the rights to use, copy, modify, merge,
9# publish, distribute, sublicense, and/or sell copies of the Software,
10# and to permit persons to whom the Software is furnished to do so,
11# subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be
14# included in all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19# NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23# SOFTWARE.
24#
25################################################################################
26
27
28
29"""
30
31Pure-Python interface to Apple Bonjour and compatible DNS-SD libraries
32
33pybonjour provides a pure-Python interface (via ctypes) to Apple
34Bonjour and compatible DNS-SD libraries (such as Avahi).  It allows
35Python scripts to take advantage of Zero Configuration Networking
36(Zeroconf) to register, discover, and resolve services on both local
37and wide-area networks.  Since pybonjour is implemented in pure
38Python, scripts that use it can easily be ported to Mac OS X, Windows,
39Linux, and other systems that run Bonjour.
40
41Note on strings: Internally, all strings used in DNS-SD are UTF-8
42strings.  String arguments passed to the DNS-SD functions provided by
43pybonjour must be either unicode instances or str instances that can
44be converted to unicode using the default encoding.  (Passing a
45non-convertible str will result in an exception.)  Strings returned
46from pybonjour (either directly from API functions or passed to
47application callbacks) are always unicode instances.
48
49"""
50
51
52__author__   = 'Christopher Stawarz <cstawarz@csail.mit.edu>'
53__version__  = '1.1.1'
54__revision__ = int('$Revision: 6125 $'.split()[1])
55
56
57import ctypes
58import os
59import re
60import socket
61import sys
62
63
64
65################################################################################
66#
67# Global setup
68#
69################################################################################
70
71
72
73class _DummyLock(object):
74
75    @staticmethod
76    def acquire():
77        pass
78
79    @staticmethod
80    def release():
81        pass
82
83_global_lock = _DummyLock()
84
85
86if sys.platform == 'win32':
87    # Need to use the stdcall variants
88    _libdnssd = ctypes.windll.dnssd
89    _CFunc = ctypes.WINFUNCTYPE
90else:
91    if sys.platform == 'darwin':
92        _libdnssd = 'libSystem.B.dylib'
93    else:
94        _libdnssd = 'libdns_sd.so.1'
95
96        # If libdns_sd is actually Avahi's Bonjour compatibility
97        # layer, silence its annoying warning messages, and use a real
98        # RLock as the global lock, since the compatibility layer
99        # isn't thread safe.
100        try:
101            ctypes.cdll.LoadLibrary('libavahi-client.so.3')
102        except OSError:
103            pass
104        else:
105            os.environ['AVAHI_COMPAT_NOWARN'] = '1'
106            import threading
107            _global_lock = threading.RLock()
108
109    _libdnssd = ctypes.cdll.LoadLibrary(_libdnssd)
110    _CFunc = ctypes.CFUNCTYPE
111
112
113
114################################################################################
115#
116# Constants
117#
118################################################################################
119
120
121
122#
123# General flags
124#
125
126kDNSServiceFlagsMoreComing          = 0x1
127kDNSServiceFlagsAdd                 = 0x2
128kDNSServiceFlagsDefault             = 0x4
129kDNSServiceFlagsNoAutoRename        = 0x8
130kDNSServiceFlagsShared              = 0x10
131kDNSServiceFlagsUnique              = 0x20
132kDNSServiceFlagsBrowseDomains       = 0x40
133kDNSServiceFlagsRegistrationDomains = 0x80
134kDNSServiceFlagsLongLivedQuery      = 0x100
135kDNSServiceFlagsAllowRemoteQuery    = 0x200
136kDNSServiceFlagsForceMulticast      = 0x400
137kDNSServiceFlagsReturnCNAME         = 0x800
138
139
140#
141# Service classes
142#
143
144kDNSServiceClass_IN                 = 1
145
146
147#
148# Service types
149#
150
151kDNSServiceType_A                   = 1
152kDNSServiceType_NS                  = 2
153kDNSServiceType_MD                  = 3
154kDNSServiceType_MF                  = 4
155kDNSServiceType_CNAME               = 5
156kDNSServiceType_SOA                 = 6
157kDNSServiceType_MB                  = 7
158kDNSServiceType_MG                  = 8
159kDNSServiceType_MR                  = 9
160kDNSServiceType_NULL                = 10
161kDNSServiceType_WKS                 = 11
162kDNSServiceType_PTR                 = 12
163kDNSServiceType_HINFO               = 13
164kDNSServiceType_MINFO               = 14
165kDNSServiceType_MX                  = 15
166kDNSServiceType_TXT                 = 16
167kDNSServiceType_RP                  = 17
168kDNSServiceType_AFSDB               = 18
169kDNSServiceType_X25                 = 19
170kDNSServiceType_ISDN                = 20
171kDNSServiceType_RT                  = 21
172kDNSServiceType_NSAP                = 22
173kDNSServiceType_NSAP_PTR            = 23
174kDNSServiceType_SIG                 = 24
175kDNSServiceType_KEY                 = 25
176kDNSServiceType_PX                  = 26
177kDNSServiceType_GPOS                = 27
178kDNSServiceType_AAAA                = 28
179kDNSServiceType_LOC                 = 29
180kDNSServiceType_NXT                 = 30
181kDNSServiceType_EID                 = 31
182kDNSServiceType_NIMLOC              = 32
183kDNSServiceType_SRV                 = 33
184kDNSServiceType_ATMA                = 34
185kDNSServiceType_NAPTR               = 35
186kDNSServiceType_KX                  = 36
187kDNSServiceType_CERT                = 37
188kDNSServiceType_A6                  = 38
189kDNSServiceType_DNAME               = 39
190kDNSServiceType_SINK                = 40
191kDNSServiceType_OPT                 = 41
192kDNSServiceType_TKEY                = 249
193kDNSServiceType_TSIG                = 250
194kDNSServiceType_IXFR                = 251
195kDNSServiceType_AXFR                = 252
196kDNSServiceType_MAILB               = 253
197kDNSServiceType_MAILA               = 254
198kDNSServiceType_ANY                 = 255
199
200
201#
202# Error codes
203#
204
205kDNSServiceErr_NoError              = 0
206kDNSServiceErr_Unknown              = -65537
207kDNSServiceErr_NoSuchName           = -65538
208kDNSServiceErr_NoMemory             = -65539
209kDNSServiceErr_BadParam             = -65540
210kDNSServiceErr_BadReference         = -65541
211kDNSServiceErr_BadState             = -65542
212kDNSServiceErr_BadFlags             = -65543
213kDNSServiceErr_Unsupported          = -65544
214kDNSServiceErr_NotInitialized       = -65545
215kDNSServiceErr_AlreadyRegistered    = -65547
216kDNSServiceErr_NameConflict         = -65548
217kDNSServiceErr_Invalid              = -65549
218kDNSServiceErr_Firewall             = -65550
219kDNSServiceErr_Incompatible         = -65551
220kDNSServiceErr_BadInterfaceIndex    = -65552
221kDNSServiceErr_Refused              = -65553
222kDNSServiceErr_NoSuchRecord         = -65554
223kDNSServiceErr_NoAuth               = -65555
224kDNSServiceErr_NoSuchKey            = -65556
225kDNSServiceErr_NATTraversal         = -65557
226kDNSServiceErr_DoubleNAT            = -65558
227kDNSServiceErr_BadTime              = -65559
228
229
230#
231# Other constants
232#
233
234kDNSServiceMaxServiceName           = 64
235kDNSServiceMaxDomainName            = 1005
236kDNSServiceInterfaceIndexAny        = 0
237kDNSServiceInterfaceIndexLocalOnly  = -1
238
239
240
241################################################################################
242#
243# Error handling
244#
245################################################################################
246
247
248
249class BonjourError(Exception):
250
251    """
252
253    Exception representing an error returned by the DNS-SD library.
254    The errorCode attribute contains the actual integer error code
255    returned.
256
257    """
258
259    _errmsg = {
260        kDNSServiceErr_NoSuchName:		'no such name',
261        kDNSServiceErr_NoMemory:		'no memory',
262        kDNSServiceErr_BadParam:		'bad param',
263        kDNSServiceErr_BadReference:		'bad reference',
264        kDNSServiceErr_BadState:		'bad state',
265        kDNSServiceErr_BadFlags:		'bad flags',
266        kDNSServiceErr_Unsupported:		'unsupported',
267        kDNSServiceErr_NotInitialized:		'not initialized',
268        kDNSServiceErr_AlreadyRegistered:	'already registered',
269        kDNSServiceErr_NameConflict:		'name conflict',
270        kDNSServiceErr_Invalid:			'invalid',
271        kDNSServiceErr_Firewall:		'firewall',
272        kDNSServiceErr_Incompatible:		'incompatible',
273        kDNSServiceErr_BadInterfaceIndex:	'bad interface index',
274        kDNSServiceErr_Refused:			'refused',
275        kDNSServiceErr_NoSuchRecord:		'no such record',
276        kDNSServiceErr_NoAuth:			'no auth',
277        kDNSServiceErr_NoSuchKey:		'no such key',
278        kDNSServiceErr_NATTraversal:		'NAT traversal',
279        kDNSServiceErr_DoubleNAT:		'double NAT',
280        kDNSServiceErr_BadTime:			'bad time',
281        }
282
283    @classmethod
284    def _errcheck(cls, result, func, args):
285        if result != kDNSServiceErr_NoError:
286            raise cls(result)
287        return args
288
289    def __init__(self, errorCode):
290        self.errorCode = errorCode
291        Exception.__init__(self,
292                           (errorCode, self._errmsg.get(errorCode, 'unknown')))
293
294
295
296################################################################################
297#
298# Data types
299#
300################################################################################
301
302
303
304class _utf8_char_p(ctypes.c_char_p):
305
306    @classmethod
307    def from_param(cls, obj):
308        if (obj is not None) and (not isinstance(obj, cls)):
309            if not str(obj):
310                raise TypeError('parameter must be a string type instance')
311
312            obj = obj.encode('utf-8')
313        return ctypes.c_char_p.from_param(obj)
314
315    def decode(self):
316        if self.value is None:
317            return None
318        return self.value.decode('utf-8')
319
320
321class _utf8_char_p_non_null(_utf8_char_p):
322
323    @classmethod
324    def from_param(cls, obj):
325        if obj is None:
326            raise ValueError('parameter cannot be None')
327        return _utf8_char_p.from_param(obj)
328
329
330_DNSServiceFlags     = ctypes.c_uint32
331_DNSServiceErrorType = ctypes.c_int32
332
333
334class DNSRecordRef(ctypes.c_void_p):
335
336    """
337
338    A DNSRecordRef pointer.  DO NOT CREATE INSTANCES OF THIS CLASS!
339    Only instances returned by the DNS-SD library are valid.  Using
340    others will likely cause the Python interpreter to crash.
341
342    Application code should not use any of the methods of this class.
343    The only valid use of a DNSRecordRef instance is as an argument to
344    a DNS-SD function.
345
346    To compare two DNSRecordRef instances for equality, use '=='
347    rather than 'is'.
348
349    """
350
351    @classmethod
352    def from_param(cls, obj):
353        if type(obj) is not cls:
354            raise TypeError("expected '%s', got '%s'" %
355                            (cls.__name__, type(obj).__name__))
356        if obj.value is None:
357            raise ValueError('invalid %s instance' % cls.__name__)
358        return obj
359
360    def __eq__(self, other):
361        return ((type(other) is type(self)) and	(other.value == self.value))
362
363    def __ne__(self, other):
364        return not (other == self)
365
366    def _invalidate(self):
367        self.value = None
368
369    def _valid(self):
370        return (self.value is not None)
371
372
373class _DNSRecordRef_or_null(DNSRecordRef):
374
375    @classmethod
376    def from_param(cls, obj):
377        if obj is None:
378            return obj
379        return DNSRecordRef.from_param(obj)
380
381
382class DNSServiceRef(DNSRecordRef):
383
384    """
385
386    A DNSServiceRef pointer.  DO NOT CREATE INSTANCES OF THIS CLASS!
387    Only instances returned by the DNS-SD library are valid.  Using
388    others will likely cause the Python interpreter to crash.
389
390    An instance of this class represents an active connection to the
391    mDNS daemon.  The connection remains open until the close() method
392    is called (which also terminates the associated browse, resolve,
393    etc.).  Note that this method is *not* called automatically when
394    the instance is deallocated; therefore, application code must be
395    certain to call close() when the connection is no longer needed.
396
397    The primary use of a DNSServiceRef instance is in conjunction with
398    select() or poll() to determine when a response from the daemon is
399    available.  When the file descriptor returned by fileno() is ready
400    for reading, a reply from the daemon is available and should be
401    processed by passing the DNSServiceRef instance to
402    DNSServiceProcessResult(), which will invoke the appropriate
403    application callback function.  (Note that the file descriptor
404    should never be read from or written to directly.)
405
406    The DNSServiceRef class supports the context management protocol
407    introduced in Python 2.5, meaning applications can use the 'with'
408    statement to ensure that DNSServiceRef instances are closed
409    regardless of whether an exception occurs, e.g.
410
411      sdRef = DNSServiceBrowse(...)
412      with sdRef:
413          # sdRef will be closed regardless of how this block is
414          # exited
415          ...
416
417    To compare two DNSServiceRef instances for equality, use '=='
418    rather than 'is'.
419
420    """
421
422    def __init__(self, *args, **kwargs):
423        DNSRecordRef.__init__(self, *args, **kwargs)
424
425        # Since callback functions are called asynchronously, we need
426        # to hold onto references to them for as long as they're in
427        # use.  Otherwise, Python could deallocate them before we call
428        # DNSServiceProcessResult(), meaning the Bonjour library would
429        # dereference freed memory when it tried to invoke the
430        # callback.
431        self._callbacks = []
432
433        # A DNSRecordRef is invalidated if DNSServiceRefDeallocate()
434        # is called on the corresponding DNSServiceRef, so we need to
435        # keep track of all our record refs and invalidate them when
436        # we're closed.
437        self._record_refs = []
438
439    def __enter__(self):
440        return self
441
442    def __exit__(self, type, value, traceback):
443        self.close()
444
445    def _add_callback(self, cb):
446        self._callbacks.append(cb)
447
448    def _add_record_ref(self, ref):
449        self._record_refs.append(ref)
450
451    def close(self):
452        """
453
454        Close the connection to the mDNS daemon and terminate any
455        associated browse, resolve, etc. operations.
456
457        """
458
459        if self._valid():
460            for ref in self._record_refs:
461                ref._invalidate()
462            del self._record_refs
463
464            _global_lock.acquire()
465            try:
466                _DNSServiceRefDeallocate(self)
467            finally:
468                _global_lock.release()
469
470            self._invalidate()
471            del self._callbacks
472
473    def fileno(self):
474        """
475
476        Return the file descriptor associated with this connection.
477        This descriptor should never be read from or written to
478        directly.  It should only be passed to select() or poll() to
479        determine when a response from the mDNS daemon is available.
480
481        """
482
483        _global_lock.acquire()
484        try:
485            fd = _DNSServiceRefSockFD(self)
486        finally:
487            _global_lock.release()
488
489        return fd
490
491
492_DNSServiceDomainEnumReply = _CFunc(
493    None,
494    DNSServiceRef,		# sdRef
495    _DNSServiceFlags,		# flags
496    ctypes.c_uint32,		# interfaceIndex
497    _DNSServiceErrorType,	# errorCode
498    _utf8_char_p,		# replyDomain
499    ctypes.c_void_p,		# context
500    )
501
502
503_DNSServiceRegisterReply = _CFunc(
504    None,
505    DNSServiceRef,		# sdRef
506    _DNSServiceFlags,		# flags
507    _DNSServiceErrorType,	# errorCode
508    _utf8_char_p,		# name
509    _utf8_char_p,		# regtype
510    _utf8_char_p,		# domain
511    ctypes.c_void_p,		# context
512    )
513
514
515_DNSServiceBrowseReply = _CFunc(
516    None,
517    DNSServiceRef,		# sdRef
518    _DNSServiceFlags,		# flags
519    ctypes.c_uint32,		# interfaceIndex
520    _DNSServiceErrorType,	# errorCode
521    _utf8_char_p,		# serviceName
522    _utf8_char_p,		# regtype
523    _utf8_char_p,		# replyDomain
524    ctypes.c_void_p,		# context
525    )
526
527
528_DNSServiceResolveReply = _CFunc(
529    None,
530    DNSServiceRef,		# sdRef
531    _DNSServiceFlags,		# flags
532    ctypes.c_uint32,		# interfaceIndex
533    _DNSServiceErrorType,	# errorCode
534    _utf8_char_p,		# fullname
535    _utf8_char_p,		# hosttarget
536    ctypes.c_uint16,		# port
537    ctypes.c_uint16,		# txtLen
538    ctypes.c_void_p,		# txtRecord (not null-terminated, so c_void_p)
539    ctypes.c_void_p,		# context
540    )
541
542
543_DNSServiceRegisterRecordReply = _CFunc(
544    None,
545    DNSServiceRef,		# sdRef
546    DNSRecordRef,		# RecordRef
547    _DNSServiceFlags,		# flags
548    _DNSServiceErrorType,	# errorCode
549    ctypes.c_void_p,		# context
550    )
551
552
553_DNSServiceQueryRecordReply = _CFunc(
554    None,
555    DNSServiceRef,		# sdRef
556    _DNSServiceFlags,		# flags
557    ctypes.c_uint32,		# interfaceIndex
558    _DNSServiceErrorType,	# errorCode
559    _utf8_char_p,		# fullname
560    ctypes.c_uint16,		# rrtype
561    ctypes.c_uint16,		# rrclass
562    ctypes.c_uint16,		# rdlen
563    ctypes.c_void_p,		# rdata
564    ctypes.c_uint32,		# ttl
565    ctypes.c_void_p,		# context
566    )
567
568
569
570################################################################################
571#
572# Low-level function bindings
573#
574################################################################################
575
576
577
578def _create_function_bindings():
579
580    ERRCHECK    = True
581    NO_ERRCHECK = False
582
583    OUTPARAM    = (lambda index: index)
584    NO_OUTPARAM = None
585
586    specs = {
587
588        #'funcname':
589        #(
590        #    return_type,
591        #    errcheck,
592        #    outparam,
593        #    (
594        #	param_1_type,
595        #	param_2_type,
596        #	...
597        #	param_n_type,
598        #	)),
599
600        'DNSServiceRefSockFD':
601        (
602            ctypes.c_int,
603            NO_ERRCHECK,
604            NO_OUTPARAM,
605            (
606                DNSServiceRef,			# sdRef
607                )),
608
609        'DNSServiceProcessResult':
610        (
611            _DNSServiceErrorType,
612            ERRCHECK,
613            NO_OUTPARAM,
614            (
615                DNSServiceRef,			# sdRef
616                )),
617
618        'DNSServiceRefDeallocate':
619        (
620            None,
621            NO_ERRCHECK,
622            NO_OUTPARAM,
623            (
624                DNSServiceRef,			# sdRef
625                )),
626
627        'DNSServiceEnumerateDomains':
628        (
629            _DNSServiceErrorType,
630            ERRCHECK,
631            OUTPARAM(0),
632            (
633                ctypes.POINTER(DNSServiceRef),	# sdRef
634                _DNSServiceFlags,		# flags
635                ctypes.c_uint32,		# interfaceIndex
636                _DNSServiceDomainEnumReply,	# callBack
637                ctypes.c_void_p,		# context
638                )),
639
640        'DNSServiceRegister':
641        (
642            _DNSServiceErrorType,
643            ERRCHECK,
644            OUTPARAM(0),
645            (
646                ctypes.POINTER(DNSServiceRef),	# sdRef
647                _DNSServiceFlags,		# flags
648                ctypes.c_uint32,		# interfaceIndex
649                _utf8_char_p,			# name
650                _utf8_char_p_non_null,		# regtype
651                _utf8_char_p,			# domain
652                _utf8_char_p,			# host
653                ctypes.c_uint16,		# port
654                ctypes.c_uint16,		# txtLen
655                ctypes.c_void_p,		# txtRecord
656                _DNSServiceRegisterReply,	# callBack
657                ctypes.c_void_p,		# context
658                )),
659
660        'DNSServiceAddRecord':
661        (
662            _DNSServiceErrorType,
663            ERRCHECK,
664            OUTPARAM(1),
665            (
666                DNSServiceRef,			# sdRef
667                ctypes.POINTER(DNSRecordRef),	# RecordRef
668                _DNSServiceFlags,		# flags
669                ctypes.c_uint16,		# rrtype
670                ctypes.c_uint16,		# rdlen
671                ctypes.c_void_p,		# rdata
672                ctypes.c_uint32,		# ttl
673                )),
674
675        'DNSServiceUpdateRecord':
676        (
677            _DNSServiceErrorType,
678            ERRCHECK,
679            NO_OUTPARAM,
680            (
681                DNSServiceRef,			# sdRef
682                _DNSRecordRef_or_null,		# RecordRef
683                _DNSServiceFlags,		# flags
684                ctypes.c_uint16,		# rdlen
685                ctypes.c_void_p,		# rdata
686                ctypes.c_uint32,		# ttl
687                )),
688
689        'DNSServiceRemoveRecord':
690        (
691            _DNSServiceErrorType,
692            ERRCHECK,
693            NO_OUTPARAM,
694            (
695                DNSServiceRef,			# sdRef
696                DNSRecordRef,			# RecordRef
697                _DNSServiceFlags,		# flags
698                )),
699
700        'DNSServiceBrowse':
701        (
702            _DNSServiceErrorType,
703            ERRCHECK,
704            OUTPARAM(0),
705            (
706                ctypes.POINTER(DNSServiceRef),	# sdRef
707                _DNSServiceFlags,		# flags
708                ctypes.c_uint32,		# interfaceIndex
709                _utf8_char_p_non_null,		# regtype
710                _utf8_char_p,			# domain
711                _DNSServiceBrowseReply,		# callBack
712                ctypes.c_void_p,		# context
713                )),
714
715        'DNSServiceResolve':
716        (
717            _DNSServiceErrorType,
718            ERRCHECK,
719            OUTPARAM(0),
720            (
721                ctypes.POINTER(DNSServiceRef),	# sdRef
722                _DNSServiceFlags,		# flags
723                ctypes.c_uint32,		# interfaceIndex
724                _utf8_char_p_non_null,		# name
725                _utf8_char_p_non_null,		# regtype
726                _utf8_char_p_non_null,		# domain
727                _DNSServiceResolveReply,	# callBack
728                ctypes.c_void_p,		# context
729                )),
730
731        'DNSServiceCreateConnection':
732        (
733            _DNSServiceErrorType,
734            ERRCHECK,
735            OUTPARAM(0),
736            (
737                ctypes.POINTER(DNSServiceRef),	# sdRef
738                )),
739
740        'DNSServiceRegisterRecord':
741        (
742            _DNSServiceErrorType,
743            ERRCHECK,
744            OUTPARAM(1),
745            (
746                DNSServiceRef,			# sdRef
747                ctypes.POINTER(DNSRecordRef),	# RecordRef
748                _DNSServiceFlags,		# flags
749                ctypes.c_uint32,		# interfaceIndex
750                _utf8_char_p_non_null,		# fullname
751                ctypes.c_uint16,		# rrtype
752                ctypes.c_uint16,		# rrclass
753                ctypes.c_uint16,		# rdlen
754                ctypes.c_void_p,		# rdata
755                ctypes.c_uint32,		# ttl
756                _DNSServiceRegisterRecordReply,	# callBack
757                ctypes.c_void_p,		# context
758                )),
759
760        'DNSServiceQueryRecord':
761        (
762            _DNSServiceErrorType,
763            ERRCHECK,
764            OUTPARAM(0),
765            (
766                ctypes.POINTER(DNSServiceRef),	# sdRef
767                _DNSServiceFlags,		# flags
768                ctypes.c_uint32,		# interfaceIndex
769                _utf8_char_p_non_null,		# fullname
770                ctypes.c_uint16,		# rrtype
771                ctypes.c_uint16,		# rrclass
772                _DNSServiceQueryRecordReply,	# callBack
773                ctypes.c_void_p,		# context
774                )),
775
776        'DNSServiceReconfirmRecord':
777        (
778            None,		# _DNSServiceErrorType in more recent versions
779            NO_ERRCHECK,
780            NO_OUTPARAM,
781            (
782                _DNSServiceFlags,		# flags
783                ctypes.c_uint32,		# interfaceIndex
784                _utf8_char_p_non_null,		# fullname
785                ctypes.c_uint16,		# rrtype
786                ctypes.c_uint16,		# rrclass
787                ctypes.c_uint16,		# rdlen
788                ctypes.c_void_p,		# rdata
789                )),
790
791        'DNSServiceConstructFullName':
792        (
793            ctypes.c_int,
794            ERRCHECK,
795            OUTPARAM(0),
796            (
797                ctypes.c_char * kDNSServiceMaxDomainName,	# fullName
798                _utf8_char_p,					# service
799                _utf8_char_p_non_null,				# regtype
800                _utf8_char_p_non_null,				# domain
801                )),
802
803        }
804
805
806    for name, (restype, errcheck, outparam, argtypes) in specs.items():
807        prototype = _CFunc(restype, *argtypes)
808
809        paramflags = [1] * len(argtypes)
810        if outparam is not None:
811            paramflags[outparam] = 2
812        paramflags = tuple((val,) for val in paramflags)
813
814        func = prototype((name, _libdnssd), paramflags)
815
816        if errcheck:
817            func.errcheck = BonjourError._errcheck
818
819        globals()['_' + name] = func
820
821
822# Only need to do this once
823_create_function_bindings()
824del _create_function_bindings
825
826
827
828################################################################################
829#
830# Internal utility types and functions
831#
832################################################################################
833
834
835
836class _NoDefault(object):
837
838    def __repr__(self):
839        return '<NO DEFAULT>'
840
841    def check(self, obj):
842        if obj is self:
843            raise ValueError('required parameter value missing')
844
845_NO_DEFAULT = _NoDefault()
846
847
848def _string_to_length_and_void_p(string):
849    if isinstance(string, TXTRecord):
850        string = str(string)
851    void_p = ctypes.cast(ctypes.c_char_p(string), ctypes.c_void_p)
852    return len(string), void_p
853
854
855def _length_and_void_p_to_string(length, void_p):
856    char_p = ctypes.cast(void_p, ctypes.POINTER(ctypes.c_char))
857    return ''.join(char_p[i].decode('utf-8') for i in range(length))
858
859
860
861################################################################################
862#
863# High-level functions
864#
865################################################################################
866
867
868
869def DNSServiceProcessResult(
870    sdRef,
871    ):
872
873    """
874
875    Read a reply from the daemon, calling the appropriate application
876    callback.  This call will block until the daemon's response is
877    received.  Use sdRef in conjunction with select() or poll() to
878    determine the presence of a response from the server before
879    calling this function to process the reply without blocking.  Call
880    this function at any point if it is acceptable to block until the
881    daemon's response arrives.  Note that the client is responsible
882    for ensuring that DNSServiceProcessResult() is called whenever
883    there is a reply from the daemon; the daemon may terminate its
884    connection with a client that does not process the daemon's
885    responses.
886
887      sdRef:
888        A DNSServiceRef returned by any of the DNSService calls that
889        take a callback parameter.
890
891    """
892
893    _global_lock.acquire()
894    try:
895        _DNSServiceProcessResult(sdRef)
896    finally:
897        _global_lock.release()
898
899
900def DNSServiceEnumerateDomains(
901    flags,
902    interfaceIndex = kDNSServiceInterfaceIndexAny,
903    callBack = None,
904    ):
905
906    """
907
908    Asynchronously enumerate domains available for browsing and
909    registration.
910
911    The enumeration MUST be cancelled by closing the returned
912    DNSServiceRef when no more domains are to be found.
913
914      flags:
915        Possible values are:
916          kDNSServiceFlagsBrowseDomains to enumerate domains
917          recommended for browsing.
918          kDNSServiceFlagsRegistrationDomains to enumerate domains
919          recommended for registration.
920
921      interfaceIndex:
922        If non-zero, specifies the interface on which to look for
923        domains.  Most applications will pass
924        kDNSServiceInterfaceIndexAny (0) to enumerate domains on all
925        interfaces.
926
927      callBack:
928        The function to be called when a domain is found or the call
929        asynchronously fails.  Its signature should be
930        callBack(sdRef,	flags, interfaceIndex, errorCode, replyDomain).
931
932      return value:
933        A DNSServiceRef instance.
934
935    Callback Parameters:
936
937      sdRef:
938        The DNSServiceRef returned by DNSServiceEnumerateDomains().
939
940      flags:
941        Possible values are:
942          kDNSServiceFlagsMoreComing
943          kDNSServiceFlagsAdd
944          kDNSServiceFlagsDefault
945
946      interfaceIndex:
947        Specifies the interface on which the domain exists.
948
949      errorCode:
950        Will be kDNSServiceErr_NoError (0) on success, otherwise
951        indicates the failure that occurred (in which case other
952        parameters are undefined).
953
954      replyDomain:
955        The name of the domain.
956
957    """
958
959    @_DNSServiceDomainEnumReply
960    def _callback(sdRef, flags, interfaceIndex, errorCode, replyDomain,
961                  context):
962        if callBack is not None:
963            callBack(sdRef, flags, interfaceIndex, errorCode,
964                     replyDomain.decode())
965
966    _global_lock.acquire()
967    try:
968        sdRef = _DNSServiceEnumerateDomains(flags,
969                                            interfaceIndex,
970                                            _callback,
971                                            None)
972    finally:
973        _global_lock.release()
974
975    sdRef._add_callback(_callback)
976
977    return sdRef
978
979
980def DNSServiceRegister(
981    flags = 0,
982    interfaceIndex = kDNSServiceInterfaceIndexAny,
983    name = None,
984    regtype = _NO_DEFAULT,
985    domain = None,
986    host = None,
987    port = _NO_DEFAULT,
988    txtRecord = '',
989    callBack = None,
990    ):
991
992    """
993
994    Register a service that is discovered via DNSServiceBrowse() and
995    DNSServiceResolve() calls.
996
997      flags:
998        Indicates the renaming behavior on name conflict.  Most
999        applications will pass 0.
1000
1001      interfaceIndex:
1002        If non-zero, specifies the interface on which to register the
1003        service.  Most applications will pass
1004        kDNSServiceInterfaceIndexAny (0) to register on all available
1005        interfaces.
1006
1007      name:
1008        If not None, specifies the service name to be registered.
1009        Most applications will not specify a name, in which case the
1010        computer name is used.  (This name is communicated to the
1011        client via the callback.)  If a name is specified, it must be
1012        1-63 bytes of UTF-8 text.  If the name is longer than 63
1013        bytes, it will be automatically truncated to a legal length,
1014        unless the flag kDNSServiceFlagsNoAutoRename is set, in which
1015        case a BonjourError exception will be thrown.
1016
1017      regtype:
1018        The service type followed by the protocol, separated by a dot
1019        (e.g. "_ftp._tcp"). The service type must be an underscore,
1020        followed by 1-14 characters, which may be letters, digits, or
1021        hyphens.  The transport protocol must be "_tcp" or "_udp". New
1022        service types should be registered at
1023        <http://www.dns-sd.org/ServiceTypes.html>.
1024
1025      domain:
1026        If not None, specifies the domain on which to advertise the
1027        service.  Most applications will not specify a domain, instead
1028        automatically registering in the default domain(s).
1029
1030      host:
1031        If not None, specifies the SRV target host name.  Most
1032        applications will not specify a host, instead automatically
1033        using the machine's default host name(s).  Note that
1034        specifying a host name does NOT create an address record for
1035        that host; the application is responsible for ensuring that
1036        the appropriate address record exists, or creating it via
1037        DNSServiceRegisterRecord().
1038
1039      port:
1040        The port, in host (not network) byte order, on which the
1041        service accepts connections.  Pass 0 for a "placeholder"
1042        service (i.e. a service that will not be discovered by
1043        browsing, but will cause a name conflict if another client
1044        tries to register that same name).  Most clients will not use
1045        placeholder services.
1046
1047      txtRecord:
1048        The TXT record rdata.  If not None, txtRecord must be either a
1049        TXTRecord instance or a string containing a properly formatted
1050        DNS TXT record, i.e.
1051        <length byte> <data> <length byte> <data> ...
1052
1053      callBack:
1054        The function to be called when the registration completes or
1055        asynchronously fails.  Its signature should be
1056        callBack(sdRef, flags, errorCode, name, regtype, domain).
1057        The client MAY pass None for the callback, in which case the
1058        client will NOT be notified of the default values picked on
1059        its behalf, and the client will NOT be notified of any
1060        asynchronous errors (e.g. out of memory errors, etc.) that may
1061        prevent the registration of the service.  The client may NOT
1062        pass the flag kDNSServiceFlagsNoAutoRename if the callback is
1063        None.  The client may still deregister the service at any time
1064        by closing the returned DNSServiceRef.
1065
1066      return value:
1067        A DNSServiceRef instance.  The registration will remain active
1068        indefinitely until the client terminates it by closing the
1069        DNSServiceRef.
1070
1071    Callback Parameters:
1072
1073      sdRef:
1074        The DNSServiceRef returned by DNSServiceRegister().
1075
1076      flags:
1077        Currently unused, reserved for future use.
1078
1079      errorCode:
1080        Will be kDNSServiceErr_NoError on success, otherwise will
1081        indicate the failure that occurred (including name conflicts,
1082        if the kDNSServiceFlagsNoAutoRename flag was used when
1083        registering).  Other parameters are undefined if an error
1084        occurred.
1085
1086      name:
1087        The service name registered.  (If the application did not
1088        specify a name in DNSServiceRegister(), this indicates what
1089        name was automatically chosen.)
1090
1091      regtype:
1092        The type of service registered, as it was passed to the
1093        callout.
1094
1095      domain:
1096        The domain on which the service was registered.  (If the
1097        application did not specify a domain in DNSServiceRegister(),
1098        this indicates the default domain on which the service was
1099        registered.)
1100
1101    """
1102
1103    _NO_DEFAULT.check(regtype)
1104    _NO_DEFAULT.check(port)
1105
1106    port = socket.htons(port)
1107
1108    # From here on txtRecord has to be a bytes type, so convert what
1109    # we have:
1110    if type(txtRecord) == TXTRecord:
1111        txtRecord = str(txtRecord).encode('utf-8')
1112    elif type(txtRecord) == str:
1113        txtRecord = txtRecord.encode('utf-8')
1114    else:
1115        raise TypeError('txtRecord is unhandlable type: {type}'.format(
1116            type=type(txtRecord)))
1117
1118    if not txtRecord:
1119        txtLen, txtRecord = 1, '\0'.encode('utf-8')
1120    else:
1121        txtLen, txtRecord = _string_to_length_and_void_p(txtRecord)
1122
1123    @_DNSServiceRegisterReply
1124    def _callback(sdRef, flags, errorCode, name, regtype, domain, context):
1125        if callBack is not None:
1126            callBack(sdRef, flags, errorCode, name.decode(), regtype.decode(),
1127                     domain.decode())
1128
1129    _global_lock.acquire()
1130    try:
1131        sdRef = _DNSServiceRegister(flags,
1132                                    interfaceIndex,
1133                                    name,
1134                                    regtype,
1135                                    domain,
1136                                    host,
1137                                    port,
1138                                    txtLen,
1139                                    txtRecord,
1140                                    _callback,
1141                                    None)
1142    finally:
1143        _global_lock.release()
1144
1145    sdRef._add_callback(_callback)
1146
1147    return sdRef
1148
1149
1150def DNSServiceAddRecord(
1151    sdRef,
1152    flags = 0,
1153    rrtype = _NO_DEFAULT,
1154    rdata = _NO_DEFAULT,
1155    ttl = 0,
1156    ):
1157
1158    """
1159
1160    Add a record to a registered service.  The name of the record will
1161    be the same as the registered service's name.  The record can
1162    later be updated or deregistered by passing the DNSRecordRef
1163    returned by this function to DNSServiceUpdateRecord() or
1164    DNSServiceRemoveRecord().
1165
1166    Note that DNSServiceAddRecord/UpdateRecord/RemoveRecord are NOT
1167    thread-safe with respect to a single DNSServiceRef.  If you plan
1168    to have multiple threads in your program simultaneously add,
1169    update, or remove records from the same DNSServiceRef, then it's
1170    the caller's responsibility to use a lock or take similar
1171    appropriate precautions to serialize those calls.
1172
1173      sdRef:
1174        A DNSServiceRef returned by DNSServiceRegister().
1175
1176      flags:
1177        Currently ignored, reserved for future use.
1178
1179      rrtype:
1180        The type of the record (e.g. kDNSServiceType_TXT,
1181        kDNSServiceType_SRV, etc.).
1182
1183      rdata:
1184        A string containing the raw rdata to be contained in the added
1185        resource record.
1186
1187      ttl:
1188        The time to live of the resource record, in seconds.  Pass 0
1189        to use a default value.
1190
1191      return value:
1192        A DNSRecordRef instance, which may be passed to
1193        DNSServiceUpdateRecord() or DNSServiceRemoveRecord().  If
1194        sdRef is closed, the DNSRecordRef is also invalidated and may
1195        not be used further.
1196
1197    """
1198
1199    _NO_DEFAULT.check(rrtype)
1200    _NO_DEFAULT.check(rdata)
1201
1202    rdlen, rdata = _string_to_length_and_void_p(rdata)
1203
1204    _global_lock.acquire()
1205    try:
1206        RecordRef = _DNSServiceAddRecord(sdRef,
1207                                         flags,
1208                                         rrtype,
1209                                         rdlen,
1210                                         rdata,
1211                                         ttl)
1212    finally:
1213        _global_lock.release()
1214
1215    sdRef._add_record_ref(RecordRef)
1216
1217    return RecordRef
1218
1219
1220def DNSServiceUpdateRecord(
1221    sdRef,
1222    RecordRef = None,
1223    flags = 0,
1224    rdata = _NO_DEFAULT,
1225    ttl = 0,
1226    ):
1227
1228    """
1229
1230    Update a registered resource record.  The record must either be:
1231      - The primary txt record of a service registered via
1232        DNSServiceRegister(), or
1233      - A record added to a registered service via
1234        DNSServiceAddRecord(), or
1235      - An individual record registered by DNSServiceRegisterRecord()
1236
1237      sdRef:
1238        A DNSServiceRef returned by DNSServiceRegister() or
1239        DNSServiceCreateConnection().
1240
1241      RecordRef:
1242        A DNSRecordRef returned by DNSServiceAddRecord(), or None to
1243        update the service's primary txt record.
1244
1245      flags:
1246        Currently ignored, reserved for future use.
1247
1248      rdata:
1249        A string containing the new rdata to be contained in the
1250        updated resource record.
1251
1252      ttl:
1253        The time to live of the updated resource record, in seconds.
1254
1255    """
1256
1257    _NO_DEFAULT.check(rdata)
1258
1259    rdlen, rdata = _string_to_length_and_void_p(rdata)
1260
1261    _global_lock.acquire()
1262    try:
1263        _DNSServiceUpdateRecord(sdRef,
1264                                RecordRef,
1265                                flags,
1266                                rdlen,
1267                                rdata,
1268                                ttl)
1269    finally:
1270        _global_lock.release()
1271
1272
1273def DNSServiceRemoveRecord(
1274    sdRef,
1275    RecordRef,
1276    flags = 0,
1277    ):
1278
1279    """
1280
1281    Remove a record previously added to a service record set via
1282    DNSServiceAddRecord(), or deregister a record registered
1283    individually via DNSServiceRegisterRecord().
1284
1285      sdRef:
1286        A DNSServiceRef returned by DNSServiceRegister() (if the
1287        record being removed was registered via DNSServiceAddRecord())
1288        or by DNSServiceCreateConnection() (if the record being
1289        removed was registered via DNSServiceRegisterRecord()).
1290
1291      recordRef:
1292        A DNSRecordRef returned by DNSServiceAddRecord() or
1293        DNSServiceRegisterRecord().
1294
1295      flags:
1296        Currently ignored, reserved for future use.
1297
1298    """
1299
1300    _global_lock.acquire()
1301    try:
1302        _DNSServiceRemoveRecord(sdRef,
1303                                RecordRef,
1304                                flags)
1305    finally:
1306        _global_lock.release()
1307
1308    RecordRef._invalidate()
1309
1310
1311def DNSServiceBrowse(
1312    flags = 0,
1313    interfaceIndex = kDNSServiceInterfaceIndexAny,
1314    regtype = _NO_DEFAULT,
1315    domain = None,
1316    callBack = None,
1317    ):
1318
1319    """
1320
1321    Browse for instances of a service.
1322
1323      flags:
1324        Currently ignored, reserved for future use.
1325
1326      interfaceIndex:
1327        If non-zero, specifies the interface on which to browse for
1328        services.  Most applications will pass
1329        kDNSServiceInterfaceIndexAny (0) to browse on all available
1330        interfaces.
1331
1332      regtype:
1333        The service type being browsed for followed by the protocol,
1334        separated by a dot (e.g. "_ftp._tcp").  The transport protocol
1335        must be "_tcp" or "_udp".
1336
1337      domain:
1338        If not None, specifies the domain on which to browse for
1339        services.  Most applications will not specify a domain,
1340        instead browsing on the default domain(s).
1341
1342      callBack:
1343        The function to be called when an instance of the service
1344        being browsed for is found, or if the call asynchronously
1345        fails.  Its signature should be
1346        callBack(sdRef, flags, interfaceIndex, errorCode,
1347                 serviceName, regtype, replyDomain).
1348
1349      return value:
1350        A DNSServiceRef instance.  The browse operation will run
1351        indefinitely until the client terminates it by closing the
1352        DNSServiceRef.
1353
1354    Callback Parameters:
1355
1356      sdRef:
1357        The DNSServiceRef returned by DNSServiceBrowse().
1358
1359      flags:
1360        Possible values are kDNSServiceFlagsMoreComing and
1361        kDNSServiceFlagsAdd.
1362
1363      interfaceIndex:
1364        The interface on which the service is advertised.  This index
1365        should be passed to DNSServiceResolve() when resolving the
1366        service.
1367
1368      errorCode:
1369        Will be kDNSServiceErr_NoError (0) on success, otherwise will
1370        indicate the failure that occurred.  Other parameters are
1371        undefined if an error occurred.
1372
1373      serviceName:
1374        The discovered service name.  This name should be displayed to
1375        the user and stored for subsequent use in the
1376        DNSServiceResolve() call.
1377
1378      regtype:
1379        The service type, which is usually (but not always) the same
1380        as was passed to DNSServiceBrowse().  One case where the
1381        discovered service type may not be the same as the requested
1382        service type is when using subtypes: The client may want to
1383        browse for only those ftp servers that allow anonymous
1384        connections.  The client will pass the string
1385        "_ftp._tcp,_anon" to DNSServiceBrowse(), but the type of the
1386        service that's discovered is simply "_ftp._tcp".  The regtype
1387        for each discovered service instance should be stored along
1388        with the name, so that it can be passed to DNSServiceResolve()
1389        when the service is later resolved.
1390
1391      replyDomain:
1392        The domain of the discovered service instance.  This may or
1393        may not be the same as the domain that was passed to
1394        DNSServiceBrowse().  The domain for each discovered service
1395        instance should be stored along with the name, so that it can
1396        be passed to DNSServiceResolve() when the service is later
1397        resolved.
1398
1399    """
1400
1401    _NO_DEFAULT.check(regtype)
1402
1403    @_DNSServiceBrowseReply
1404    def _callback(sdRef, flags, interfaceIndex, errorCode, serviceName, regtype,
1405                  replyDomain, context):
1406        if callBack is not None:
1407            callBack(sdRef, flags, interfaceIndex, errorCode,
1408                     serviceName.decode(), regtype.decode(),
1409                     replyDomain.decode())
1410
1411    _global_lock.acquire()
1412    try:
1413        sdRef = _DNSServiceBrowse(flags,
1414                                  interfaceIndex,
1415                                  regtype,
1416                                  domain,
1417                                  _callback,
1418                                  None)
1419    finally:
1420        _global_lock.release()
1421
1422    sdRef._add_callback(_callback)
1423
1424    return sdRef
1425
1426
1427def DNSServiceResolve(
1428    flags = 0,
1429    interfaceIndex = _NO_DEFAULT,
1430    name = _NO_DEFAULT,
1431    regtype = _NO_DEFAULT,
1432    domain = _NO_DEFAULT,
1433    callBack = None,
1434    ):
1435
1436    """
1437
1438    Resolve a service name discovered via DNSServiceBrowse() to a
1439    target host name, port number, and txt record.
1440
1441    Note: Applications should NOT use DNSServiceResolve() solely for
1442    txt record monitoring; use DNSServiceQueryRecord() instead, as it
1443    is more efficient for this task.
1444
1445    Note: When the desired results have been returned, the client MUST
1446    terminate the resolve by closing the returned DNSServiceRef.
1447
1448    Note: DNSServiceResolve() behaves correctly for typical services
1449    that have a single SRV record and a single TXT record.  To resolve
1450    non-standard services with multiple SRV or TXT records,
1451    DNSServiceQueryRecord() should be used.
1452
1453      flags:
1454        Currently ignored, reserved for future use.
1455
1456      interfaceIndex:
1457        The interface on which to resolve the service.  If this
1458        resolve call is as a result of a currently active
1459        DNSServiceBrowse() operation, then the interfaceIndex should
1460        be the index reported in the browse callback.  If this resolve
1461        call is using information previously saved (e.g. in a
1462        preference file) for later use, then use
1463        kDNSServiceInterfaceIndexAny (0), because the desired service
1464        may now be reachable via a different physical interface.
1465
1466      name:
1467        The name of the service instance to be resolved, as reported
1468        to the DNSServiceBrowse() callback.
1469
1470      regtype:
1471        The type of the service instance to be resolved, as reported
1472        to the DNSServiceBrowse() callback.
1473
1474      domain:
1475        The domain of the service instance to be resolved, as reported
1476        to the DNSServiceBrowse() callback.
1477
1478      callBack:
1479        The function to be called when a result is found, or if the
1480        call asynchronously fails.  Its signature should be
1481        callBack(sdRef, flags, interfaceIndex, errorCode, fullname,
1482                 hosttarget, port, txtRecord).
1483
1484      return value:
1485        A DNSServiceRef instance.  The resolve operation will run
1486        indefinitely until the client terminates it by closing the
1487        DNSServiceRef.
1488
1489    Callback Parameters:
1490
1491      sdRef:
1492        The DNSServiceRef returned by DNSServiceResolve().
1493
1494      flags:
1495        Currently unused, reserved for future use.
1496
1497      interfaceIndex:
1498        The interface on which the service was resolved.
1499
1500      errorCode:
1501        Will be kDNSServiceErr_NoError (0) on success, otherwise will
1502        indicate the failure that occurred.  Other parameters are
1503        undefined if an error occurred.
1504
1505      fullname:
1506        The full service domain name, in the form
1507        <servicename>.<protocol>.<domain>.
1508
1509      hosttarget:
1510        The target hostname of the machine providing the service.
1511
1512      port:
1513        The port, in host (not network) byte order, on which
1514        connections are accepted for this service.
1515
1516      txtRecord:
1517        A string containing the service's primary txt record, in
1518        standard txt record format.
1519
1520    """
1521
1522    _NO_DEFAULT.check(interfaceIndex)
1523    _NO_DEFAULT.check(name)
1524    _NO_DEFAULT.check(regtype)
1525    _NO_DEFAULT.check(domain)
1526
1527    @_DNSServiceResolveReply
1528    def _callback(sdRef, flags, interfaceIndex, errorCode, fullname, hosttarget,
1529                  port, txtLen, txtRecord, context):
1530        if callBack is not None:
1531            port = socket.ntohs(port)
1532            txtRecord = _length_and_void_p_to_string(txtLen, txtRecord)
1533            callBack(sdRef, flags, interfaceIndex, errorCode, fullname.decode(),
1534                     hosttarget.decode(), port, txtRecord)
1535
1536    _global_lock.acquire()
1537    try:
1538        sdRef = _DNSServiceResolve(flags,
1539                                   interfaceIndex,
1540                                   name,
1541                                   regtype,
1542                                   domain,
1543                                   _callback,
1544                                   None)
1545    finally:
1546        _global_lock.release()
1547
1548    sdRef._add_callback(_callback)
1549
1550    return sdRef
1551
1552
1553def DNSServiceCreateConnection():
1554
1555    """
1556
1557    Create a connection to the daemon allowing efficient registration
1558    of multiple individual records.
1559
1560      return value:
1561        A DNSServiceRef instance.  Closing it severs the connection
1562        and deregisters all records registered on this connection.
1563
1564    """
1565
1566    _global_lock.acquire()
1567    try:
1568        sdRef = _DNSServiceCreateConnection()
1569    finally:
1570        _global_lock.release()
1571
1572    return sdRef
1573
1574
1575def DNSServiceRegisterRecord(
1576    sdRef,
1577    flags,
1578    interfaceIndex = kDNSServiceInterfaceIndexAny,
1579    fullname = _NO_DEFAULT,
1580    rrtype = _NO_DEFAULT,
1581    rrclass = kDNSServiceClass_IN,
1582    rdata = _NO_DEFAULT,
1583    ttl = 0,
1584    callBack = None,
1585    ):
1586
1587    """
1588
1589    Register an individual resource record on a connected
1590    DNSServiceRef.
1591
1592    Note that name conflicts occurring for records registered via this
1593    call must be handled by the client in the callback.
1594
1595      sdRef:
1596        A DNSServiceRef returned by DNSServiceCreateConnection().
1597
1598      flags:
1599        Possible values are kDNSServiceFlagsShared or
1600        kDNSServiceFlagsUnique.
1601
1602      interfaceIndex:
1603        If non-zero, specifies the interface on which to register the
1604        record.  Passing kDNSServiceInterfaceIndexAny (0) causes the
1605        record to be registered on all interfaces.
1606
1607      fullname:
1608        The full domain name of the resource record.
1609
1610      rrtype:
1611        The numerical type of the resource record
1612        (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc.).
1613
1614      rrclass:
1615        The class of the resource record (usually
1616        kDNSServiceClass_IN).
1617
1618      rdata:
1619        A string containing the raw rdata, as it is to appear in the
1620        DNS record.
1621
1622      ttl:
1623        The time to live of the resource record, in seconds.  Pass 0
1624        to use a default value.
1625
1626      callBack:
1627        The function to be called when a result is found, or if the
1628        call asynchronously fails (e.g. because of a name conflict).
1629        Its signature should be
1630        callBack(sdRef, RecordRef, flags, errorCode).
1631
1632      return value:
1633        A DNSRecordRef instance, which may be passed to
1634        DNSServiceUpdateRecord() or DNSServiceRemoveRecord().  (To
1635        deregister ALL records registered on a single connected
1636        DNSServiceRef and deallocate each of their corresponding
1637        DNSRecordRefs, close the DNSServiceRef.)
1638
1639    Callback Parameters:
1640
1641      sdRef:
1642        The connected DNSServiceRef returned by
1643        DNSServiceCreateConnection().
1644
1645      RecordRef:
1646        The DNSRecordRef returned by DNSServiceRegisterRecord().
1647
1648      flags:
1649        Currently unused, reserved for future use.
1650
1651      errorCode:
1652        Will be kDNSServiceErr_NoError on success, otherwise will
1653        indicate the failure that occurred (including name conflicts).
1654        Other parameters are undefined if an error occurred.
1655
1656    """
1657
1658    _NO_DEFAULT.check(fullname)
1659    _NO_DEFAULT.check(rrtype)
1660    _NO_DEFAULT.check(rdata)
1661
1662    rdlen, rdata = _string_to_length_and_void_p(rdata)
1663
1664    @_DNSServiceRegisterRecordReply
1665    def _callback(sdRef, RecordRef, flags, errorCode, context):
1666        if callBack is not None:
1667            callBack(sdRef, RecordRef, flags, errorCode)
1668
1669    _global_lock.acquire()
1670    try:
1671        RecordRef = _DNSServiceRegisterRecord(sdRef,
1672                                              flags,
1673                                              interfaceIndex,
1674                                              fullname,
1675                                              rrtype,
1676                                              rrclass,
1677                                              rdlen,
1678                                              rdata,
1679                                              ttl,
1680                                              _callback,
1681                                              None)
1682    finally:
1683        _global_lock.release()
1684
1685    sdRef._add_callback(_callback)
1686    sdRef._add_record_ref(RecordRef)
1687
1688    return RecordRef
1689
1690
1691def DNSServiceQueryRecord(
1692    flags = 0,
1693    interfaceIndex = kDNSServiceInterfaceIndexAny,
1694    fullname = _NO_DEFAULT,
1695    rrtype = _NO_DEFAULT,
1696    rrclass = kDNSServiceClass_IN,
1697    callBack = None,
1698    ):
1699
1700    """
1701
1702    Query for an arbitrary DNS record.
1703
1704      flags:
1705        Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived"
1706        unicast query in a non-local domain.  Without setting this
1707        flag, unicast queries will be one-shot; that is, only answers
1708        available at the time of the call will be returned.  By
1709        setting this flag, answers (including Add and Remove events)
1710        that become available after the initial call is made will
1711        generate callbacks.  This flag has no effect on link-local
1712        multicast queries.
1713
1714      interfaceIndex:
1715        If non-zero, specifies the interface on which to issue the
1716        query.  Passing kDNSServiceInterfaceIndexAny (0) causes the
1717        name to be queried for on all interfaces.
1718
1719      fullname:
1720        The full domain name of the resource record to be queried for.
1721
1722      rrtype:
1723        The numerical type of the resource record to be queried for
1724        (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc.).
1725
1726      rrclass:
1727        The class of the resource record (usually
1728        kDNSServiceClass_IN).
1729
1730      callBack:
1731        The function to be called when a result is found, or if the
1732        call asynchronously fails.  Its signature should be
1733        callBack(sdRef, flags, interfaceIndex, errorCode, fullname,
1734                 rrtype, rrclass, rdata, ttl).
1735
1736      return value:
1737        A DNSServiceRef instance.  The query operation will run
1738        indefinitely until the client terminates it by closing the
1739        DNSServiceRef.
1740
1741    Callback Parameters:
1742
1743      sdRef:
1744        The DNSServiceRef returned by DNSServiceQueryRecord().
1745
1746      flags:
1747        Possible values are kDNSServiceFlagsMoreComing and
1748        kDNSServiceFlagsAdd.  The Add flag is NOT set for PTR records
1749        with a ttl of 0, i.e. "Remove" events.
1750
1751      interfaceIndex:
1752        The interface on which the query was resolved.
1753
1754      errorCode:
1755        Will be kDNSServiceErr_NoError on success, otherwise will
1756        indicate the failure that occurred.  Other parameters are
1757        undefined if an error occurred.
1758
1759      fullname:
1760        The resource record's full domain name.
1761
1762      rrtype:
1763        The resource record's type (e.g. kDNSServiceType_PTR,
1764        kDNSServiceType_SRV, etc.).
1765
1766      rrclass:
1767        The class of the resource record (usually
1768        kDNSServiceClass_IN).
1769
1770      rdata:
1771        A string containing the raw rdata of the resource record.
1772
1773      ttl:
1774        The resource record's time to live, in seconds.
1775
1776    """
1777
1778    _NO_DEFAULT.check(fullname)
1779    _NO_DEFAULT.check(rrtype)
1780
1781    @_DNSServiceQueryRecordReply
1782    def _callback(sdRef, flags, interfaceIndex, errorCode, fullname, rrtype,
1783                  rrclass, rdlen, rdata, ttl, context):
1784        if callBack is not None:
1785            rdata = _length_and_void_p_to_string(rdlen, rdata)
1786            callBack(sdRef, flags, interfaceIndex, errorCode, fullname.decode(),
1787                     rrtype, rrclass, rdata, ttl)
1788
1789    _global_lock.acquire()
1790    try:
1791        sdRef = _DNSServiceQueryRecord(flags,
1792                                       interfaceIndex,
1793                                       fullname,
1794                                       rrtype,
1795                                       rrclass,
1796                                       _callback,
1797                                       None)
1798    finally:
1799        _global_lock.release()
1800
1801    sdRef._add_callback(_callback)
1802
1803    return sdRef
1804
1805
1806def DNSServiceReconfirmRecord(
1807    flags = 0,
1808    interfaceIndex = kDNSServiceInterfaceIndexAny,
1809    fullname = _NO_DEFAULT,
1810    rrtype = _NO_DEFAULT,
1811    rrclass = kDNSServiceClass_IN,
1812    rdata = _NO_DEFAULT,
1813    ):
1814
1815    """
1816
1817    Instruct the daemon to verify the validity of a resource record
1818    that appears to be out of date (e.g. because tcp connection to a
1819    service's target failed).  Causes the record to be flushed from
1820    the daemon's cache (as well as all other daemons' caches on the
1821    network) if the record is determined to be invalid.
1822
1823      flags:
1824        Currently unused, reserved for future use.
1825
1826      interfaceIndex:
1827        If non-zero, specifies the interface of the record in
1828        question.  Passing kDNSServiceInterfaceIndexAny (0) causes all
1829        instances of this record to be reconfirmed.
1830
1831      fullname:
1832        The resource record's full domain name.
1833
1834      rrtype:
1835        The resource record's type (e.g. kDNSServiceType_PTR,
1836        kDNSServiceType_SRV, etc.).
1837
1838      rrclass:
1839        The class of the resource record (usually
1840        kDNSServiceClass_IN).
1841
1842      rdata:
1843        A string containing the raw rdata of the resource record.
1844
1845    """
1846
1847    _NO_DEFAULT.check(fullname)
1848    _NO_DEFAULT.check(rrtype)
1849    _NO_DEFAULT.check(rdata)
1850
1851    rdlen, rdata = _string_to_length_and_void_p(rdata)
1852
1853    _global_lock.acquire()
1854    try:
1855        _DNSServiceReconfirmRecord(flags,
1856                                   interfaceIndex,
1857                                   fullname,
1858                                   rrtype,
1859                                   rrclass,
1860                                   rdlen,
1861                                   rdata)
1862    finally:
1863        _global_lock.release()
1864
1865
1866def DNSServiceConstructFullName(
1867    service = None,
1868    regtype = _NO_DEFAULT,
1869    domain = _NO_DEFAULT,
1870    ):
1871
1872    """
1873
1874    Concatenate a three-part domain name (as returned by a callback
1875    function) into a properly-escaped full domain name.  Note that
1876    callback functions already escape strings where necessary.
1877
1878      service:
1879        The service name; any dots or backslashes must NOT be escaped.
1880        May be None (to construct a PTR record name, e.g.
1881        "_ftp._tcp.apple.com.").
1882
1883      regtype:
1884        The service type followed by the protocol, separated by a dot
1885        (e.g. "_ftp._tcp").
1886
1887      domain:
1888        The domain name, e.g. "apple.com.".  Literal dots or
1889        backslashes, if any, must be escaped,
1890        e.g. "1st\. Floor.apple.com."
1891
1892      return value:
1893        The resulting full domain name.
1894
1895    """
1896
1897    _NO_DEFAULT.check(regtype)
1898    _NO_DEFAULT.check(domain)
1899
1900    _global_lock.acquire()
1901    try:
1902        fullName = _DNSServiceConstructFullName(service, regtype, domain)
1903    finally:
1904        _global_lock.release()
1905
1906    return fullName.value.decode('utf-8')
1907
1908
1909
1910################################################################################
1911#
1912# TXTRecord class
1913#
1914################################################################################
1915
1916
1917
1918class TXTRecord(object):
1919
1920    """
1921
1922    A mapping representing a DNS TXT record.  The TXT record's
1923    name=value entries are stored as key/value pairs in the mapping.
1924    Although keys can be accessed in a case-insensitive fashion
1925    (meaning txt['foo'] and txt['FoO'] refer to the same value), key
1926    case is preserved in the wire representation of the record (so
1927    txt['FoO'] = 'bar' will generate a FoO=bar entry in the TXT
1928    record).  Key order is also preserved, so keys appear in the wire
1929    format in the order in which they were created.
1930
1931    Note that in addition to being valid as a txtRecord parameter to
1932    DNSServiceRegister(), a TXTRecord instance can be used in place of
1933    a resource record data string (i.e. rdata parameter) with any
1934    function that accepts one.
1935
1936    """
1937
1938    def __init__(self, items={}, strict=True):
1939        """
1940
1941        Create a new TXTRecord instance, initializing it with the
1942        contents of items.  If strict is true, then strict conformance
1943        to the DNS TXT record format will be enforced, and attempts to
1944        add a name containing invalid characters or a name/value pair
1945        whose wire representation is longer than 255 bytes will raise
1946        a ValueError exception.
1947
1948        """
1949
1950        self.strict = strict
1951        self._names = []
1952        self._items = {}
1953
1954        for name, value in items.items():
1955            self[name] = value
1956
1957    def __contains__(self, name):
1958        'Return True if name is a key in the record, False otherwise'
1959        return (name.lower() in self._items)
1960
1961    def __iter__(self):
1962        'Return an iterator over name/value pairs'
1963        for name in self._names:
1964            yield self._items[name]
1965
1966    def __len__(self):
1967        'Return the number of name/value pairs'
1968        return len(self._names)
1969
1970    def __nonzero__(self):
1971        'Return False if the record is empty, True otherwise'
1972        return bool(self._items)
1973
1974    def __str__(self):
1975        """
1976
1977        Return the wire representation of the TXT record as a string.
1978        If self.strict is false, any name/value pair whose wire length
1979        if greater than 255 bytes will be truncated to 255 bytes.  If
1980        the record is empty, '\\0' is returned.
1981
1982        """
1983
1984        if not self:
1985            return '\0'
1986
1987        parts = []
1988        for name, value in self:
1989            if value is None:
1990                item = name
1991            else:
1992                item = '%s=%s' % (name, value)
1993            if (not self.strict) and (len(item) > 255):
1994                item = item[:255]
1995            parts.append(chr(len(item)))
1996            parts.append(item)
1997
1998        return ''.join(parts)
1999
2000    def __getitem__(self, name):
2001        """
2002
2003        Return the value associated with name.  The value is either
2004        None (meaning name has no associated value) or an str instance
2005        (which may be of length 0).  Raises KeyError if name is not a
2006        key.
2007
2008        """
2009        return self._items[name.lower()][1]
2010
2011    # Require one or more printable ASCII characters (0x20-0x7E),
2012    # excluding '=' (0x3D)
2013    _valid_name_re = re.compile(r'^[ -<>-~]+$')
2014
2015    def __setitem__(self, name, value):
2016        """
2017
2018        Add a name/value pair to the record.  If value is None, then
2019        name will have no associated value.  If value is a unicode
2020        instance, it will be encoded as a UTF-8 string.  Otherwise,
2021        value will be converted to an str instance.
2022
2023        """
2024
2025        stored_name = name
2026        name = name.lower()
2027        length = len(name)
2028
2029        if value is not None:
2030            value = str(value)
2031            length += 1 + len(value)
2032
2033        if self.strict and (length > 255):
2034            raise ValueError('name=value string must be 255 bytes or less')
2035
2036        if name not in self._items:
2037            if self.strict and (self._valid_name_re.match(stored_name) is None):
2038                raise ValueError("invalid name: '%s'" % stored_name)
2039            self._names.append(name)
2040
2041        self._items[name] = (stored_name, value)
2042
2043    def __delitem__(self, name):
2044        """
2045
2046        Remove name and its corresponding value from the record.
2047        Raises KeyError if name is not a key.
2048
2049        """
2050        name = name.lower()
2051        del self._items[name]
2052        self._names.remove(name)
2053
2054    @classmethod
2055    def parse(cls, data, strict=False):
2056        """
2057
2058        Given a string data containing the wire representation of a
2059        DNS TXT record, parse it and return a TXTRecord instance.  The
2060        strict parameter is passed to the TXTRecord constructor.
2061
2062        """
2063
2064        txt = cls(strict=strict)
2065
2066        while data:
2067            length = ord(data[0])
2068            item = data[1:length+1].split('=', 1)
2069
2070            # Add the item only if the name is non-empty and there are
2071            # no existing items with the same name
2072            if item[0] and (item[0] not in txt):
2073                if len(item) == 1:
2074                    txt[item[0]] = None
2075                else:
2076                    txt[item[0]] = item[1]
2077
2078            data = data[length+1:]
2079
2080        return txt
2081