1
+ from __future__ import absolute_import , division , print_function , unicode_literals
2
+
1
3
""" Multicast DNS Service Discovery for Python, v0.14-wmcbrine
2
4
Copyright 2003 Paul Scott-Murphy, 2014 William McBrine
3
5
31
33
import threading
32
34
import select
33
35
import traceback
36
+ from functools import reduce
34
37
35
38
__all__ = ["Zeroconf" , "ServiceInfo" , "ServiceBrowser" ]
36
39
40
+ try :
41
+ xrange = xrange
42
+ except NameError :
43
+ xrange = range
44
+
45
+ try :
46
+ unicode
47
+ except NameError :
48
+ unicode = str
49
+
50
+ if isinstance (chr (8 ), unicode ):
51
+ byte_chr = lambda num : bytes ([num ])
52
+ else :
53
+ byte_chr = chr
54
+
55
+ if isinstance (bytes ([8 ])[0 ], int ):
56
+ byte_ord = lambda x : x
57
+ else :
58
+ byte_ord = ord
59
+
37
60
# hook for threads
38
61
39
62
_GLOBAL_DONE = False
@@ -359,6 +382,7 @@ class DNSText(DNSRecord):
359
382
"""A DNS text record"""
360
383
361
384
def __init__ (self , name , type , clazz , ttl , text ):
385
+ assert isinstance (text , bytes )
362
386
DNSRecord .__init__ (self , name , type , clazz , ttl )
363
387
self .text = text
364
388
@@ -437,24 +461,24 @@ def unpack(self, format):
437
461
def readHeader (self ):
438
462
"""Reads header portion of packet"""
439
463
(self .id , self .flags , self .numQuestions , self .numAnswers ,
440
- self .numAuthorities , self .numAdditionals ) = self .unpack ('!6H' )
464
+ self .numAuthorities , self .numAdditionals ) = self .unpack (b '!6H' )
441
465
442
466
def readQuestions (self ):
443
467
"""Reads questions section of packet"""
444
468
for i in xrange (self .numQuestions ):
445
469
name = self .readName ()
446
- type , clazz = self .unpack ('!HH' )
470
+ type , clazz = self .unpack (b '!HH' )
447
471
448
472
question = DNSQuestion (name , type , clazz )
449
473
self .questions .append (question )
450
474
451
475
def readInt (self ):
452
476
"""Reads an integer from the packet"""
453
- return self .unpack ('!I' )[0 ]
477
+ return self .unpack (b '!I' )[0 ]
454
478
455
479
def readCharacterString (self ):
456
480
"""Reads a character string from the packet"""
457
- length = ord (self .data [self .offset ])
481
+ length = byte_ord (self .data [self .offset ])
458
482
self .offset += 1
459
483
return self .readString (length )
460
484
@@ -466,15 +490,15 @@ def readString(self, length):
466
490
467
491
def readUnsignedShort (self ):
468
492
"""Reads an unsigned short from the packet"""
469
- return self .unpack ('!H' )[0 ]
493
+ return self .unpack (b '!H' )[0 ]
470
494
471
495
def readOthers (self ):
472
496
"""Reads the answers, authorities and additionals section of the
473
497
packet"""
474
498
n = self .numAnswers + self .numAuthorities + self .numAdditionals
475
499
for i in xrange (n ):
476
500
domain = self .readName ()
477
- type , clazz , ttl , length = self .unpack ('!HHiH' )
501
+ type , clazz , ttl , length = self .unpack (b '!HHiH' )
478
502
479
503
rec = None
480
504
if type == _TYPE_A :
@@ -521,7 +545,7 @@ def readName(self):
521
545
first = off
522
546
523
547
while True :
524
- length = ord (self .data [off ])
548
+ length = byte_ord (self .data [off ])
525
549
off += 1
526
550
if length == 0 :
527
551
break
@@ -532,12 +556,14 @@ def readName(self):
532
556
elif t == 0xC0 :
533
557
if next < 0 :
534
558
next = off + 1
535
- off = ((length & 0x3F ) << 8 ) | ord (self .data [off ])
559
+ off = ((length & 0x3F ) << 8 ) | byte_ord (self .data [off ])
536
560
if off >= first :
537
- raise "Bad domain name (circular) at " + str (off )
561
+ # TODO raise more specific exception
562
+ raise Exception ("Bad domain name (circular) at %s" % (off ,))
538
563
first = off
539
564
else :
540
- raise "Bad domain name at " + str (off )
565
+ # TODO raise more specific exception
566
+ raise Exception ("Bad domain name at %s" % (off ,))
541
567
542
568
if next >= 0 :
543
569
self .offset = next
@@ -594,23 +620,24 @@ def pack(self, format, value):
594
620
595
621
def writeByte (self , value ):
596
622
"""Writes a single byte to the packet"""
597
- self .pack ('!c' , chr (value ))
623
+ self .pack (b '!c' , byte_chr (value ))
598
624
599
625
def insertShort (self , index , value ):
600
626
"""Inserts an unsigned short in a certain position in the packet"""
601
- self .data .insert (index , struct .pack ('!H' , value ))
627
+ self .data .insert (index , struct .pack (b '!H' , value ))
602
628
self .size += 2
603
629
604
630
def writeShort (self , value ):
605
631
"""Writes an unsigned short to the packet"""
606
- self .pack ('!H' , value )
632
+ self .pack (b '!H' , value )
607
633
608
634
def writeInt (self , value ):
609
635
"""Writes an unsigned integer to the packet"""
610
- self .pack ('!I' , int (value ))
636
+ self .pack (b '!I' , int (value ))
611
637
612
638
def writeString (self , value ):
613
639
"""Writes a string to the packet"""
640
+ assert isinstance (value , bytes )
614
641
self .data .append (value )
615
642
self .size += len (value )
616
643
@@ -674,7 +701,7 @@ def writeRecord(self, record, now):
674
701
record .write (self )
675
702
self .size -= 2
676
703
677
- length = len ('' .join (self .data [index :]))
704
+ length = len (b '' .join (self .data [index :]))
678
705
self .insertShort (index , length ) # Here is the short we adjusted for
679
706
680
707
def packet (self ):
@@ -702,7 +729,7 @@ def packet(self):
702
729
self .insertShort (0 , 0 )
703
730
else :
704
731
self .insertShort (0 , self .id )
705
- return '' .join (self .data )
732
+ return b '' .join (self .data )
706
733
707
734
708
735
class DNSCache (object ):
@@ -843,7 +870,7 @@ def __init__(self, zc):
843
870
def handle_read (self ):
844
871
try :
845
872
data , (addr , port ) = self .zc .socket .recvfrom (_MAX_MSG_ABSOLUTE )
846
- except socket .error , e :
873
+ except socket .error as e :
847
874
# If the socket was closed by another thread -- which happens
848
875
# regularly on shutdown -- an EBADF exception is thrown here.
849
876
# Ignore it.
@@ -1009,23 +1036,26 @@ def setProperties(self, properties):
1009
1036
if isinstance (properties , dict ):
1010
1037
self .properties = properties
1011
1038
list = []
1012
- result = ''
1039
+ result = b ''
1013
1040
for key in properties :
1014
1041
value = properties [key ]
1042
+ if isinstance (key , unicode ):
1043
+ key = key .encode ('utf-8' )
1044
+
1015
1045
if value is None :
1016
- suffix = '' . encode ( 'utf-8' )
1017
- elif isinstance (value , str ):
1046
+ suffix = b''
1047
+ elif isinstance (value , unicode ):
1018
1048
suffix = value .encode ('utf-8' )
1019
1049
elif isinstance (value , int ):
1020
1050
if value :
1021
- suffix = 'true'
1051
+ suffix = b 'true'
1022
1052
else :
1023
- suffix = 'false'
1053
+ suffix = b 'false'
1024
1054
else :
1025
- suffix = '' . encode ( 'utf-8' )
1026
- list .append ('=' .join ((key , suffix )))
1055
+ suffix = b''
1056
+ list .append (b '=' .join ((key , suffix )))
1027
1057
for item in list :
1028
- result = '' .join ((result , chr (len (item )), item ))
1058
+ result = b '' .join ((result , byte_chr (len (item )), item ))
1029
1059
self .text = result
1030
1060
else :
1031
1061
self .text = properties
@@ -1039,7 +1069,7 @@ def setText(self, text):
1039
1069
index = 0
1040
1070
strs = []
1041
1071
while index < end :
1042
- length = ord (text [index ])
1072
+ length = byte_ord (text [index ])
1043
1073
index += 1
1044
1074
strs .append (text [index :index + length ])
1045
1075
index += length
@@ -1561,26 +1591,25 @@ def close(self):
1561
1591
# query (for Zoe), and service unregistration.
1562
1592
1563
1593
if __name__ == '__main__' :
1564
- print "Multicast DNS Service Discovery for Python, version" , __version__
1594
+ print ( "Multicast DNS Service Discovery for Python, version %s" % __version__ )
1565
1595
r = Zeroconf ()
1566
- print "1. Testing registration of a service..."
1596
+ print ( "1. Testing registration of a service..." )
1567
1597
desc = {'version' : '0.10' , 'a' : 'test value' , 'b' : 'another value' }
1568
1598
info = ServiceInfo ("_http._tcp.local." ,
1569
1599
"My Service Name._http._tcp.local." ,
1570
1600
socket .inet_aton ("127.0.0.1" ), 1234 , 0 , 0 , desc )
1571
- print " Registering service..."
1601
+ print ( " Registering service..." )
1572
1602
r .registerService (info )
1573
- print " Registration done."
1574
- print "2. Testing query of service information..."
1575
- print " Getting ZOE service:" ,
1576
- print str (r .getServiceInfo ("_http._tcp.local." , "ZOE._http._tcp.local." ))
1577
- print " Query done."
1578
- print "3. Testing query of own service..."
1579
- print " Getting self:" ,
1580
- print str (r .getServiceInfo ("_http._tcp.local." ,
1581
- "My Service Name._http._tcp.local." ))
1582
- print " Query done."
1583
- print "4. Testing unregister of service information..."
1603
+ print (" Registration done." )
1604
+ print ("2. Testing query of service information..." )
1605
+ print (" Getting ZOE service: %s" % (
1606
+ r .getServiceInfo ("_http._tcp.local." , "ZOE._http._tcp.local." )))
1607
+ print (" Query done." )
1608
+ print ("3. Testing query of own service..." )
1609
+ print (" Getting self: %s" % (
1610
+ r .getServiceInfo ("_http._tcp.local." , "My Service Name._http._tcp.local." )),)
1611
+ print (" Query done." )
1612
+ print ("4. Testing unregister of service information..." )
1584
1613
r .unregisterService (info )
1585
- print " Unregister done."
1614
+ print ( " Unregister done." )
1586
1615
r .close ()
0 commit comments