annotate hgext/zeroconf/Zeroconf.py @ 36523:e7411fb7ba7f

wireprotoserver: ability to run an SSH server until an event is set It seems useful to be able to start an SSH protocol server that won't run forever and won't call sys.exit() when it stops. This could be used to facilitate intra-process testing of the SSH protocol, for example. We teach the server function to loop until a threading.Event is set and invent a new API to run the server until an event is set. It also won't sys.exit() afterwards. There aren't many callers of serve_forever(). So we could refactor them relatively easily. But I was lazy. threading.Event might be a bit heavyweight. An alternative would be a list whose only elements is changed. We can't use a simple scalar value like a bool or int because those types are immutable. Events are what you use in systems programming for this use case, so the use of threading.Event seems justified. Differential Revision: https://phab.mercurial-scm.org/D2461
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 24 Feb 2018 12:07:21 -0800
parents 31451f3f4b56
children 876494fd967d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
28296
a73394e7b47c zeroconf: use absolute_import
timeless <timeless@mozdev.org>
parents: 28295
diff changeset
1 from __future__ import absolute_import, print_function
28295
01815c159856 zeroconf: use print function
timeless <timeless@mozdev.org>
parents: 28249
diff changeset
2
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 """ Multicast DNS Service Discovery for Python, v0.12
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 Copyright (C) 2003, Paul Scott-Murphy
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
5
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
6 This module provides a framework for the use of DNS Service Discovery
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7 using IP multicast. It has been tested against the JRendezvous
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
8 implementation from <a href="http://strangeberry.com">StrangeBerry</a>,
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
9 and against the mDNSResponder from Mac OS X 10.3.8.
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
10
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11 This library is free software; you can redistribute it and/or
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
12 modify it under the terms of the GNU Lesser General Public
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
13 License as published by the Free Software Foundation; either
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14 version 2.1 of the License, or (at your option) any later version.
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
15
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
16 This library is distributed in the hope that it will be useful,
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
19 Lesser General Public License for more details.
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
20
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
21 You should have received a copy of the GNU Lesser General Public
15782
7de7630053cb Remove FSF mailing address from GPL headers
Martin Geisler <mg@aragost.com>
parents: 14494
diff changeset
22 License along with this library; if not, see
7de7630053cb Remove FSF mailing address from GPL headers
Martin Geisler <mg@aragost.com>
parents: 14494
diff changeset
23 <http://www.gnu.org/licenses/>.
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
24
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
25 """
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
26
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27 """0.12 update - allow selection of binding interface
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
28 typo fix - Thanks A. M. Kuchlingi
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
29 removed all use of word 'Rendezvous' - this is an API change"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
30
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
31 """0.11 update - correction to comments for addListener method
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
32 support for new record types seen from OS X
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
33 - IPv6 address
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
34 - hostinfo
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
35 ignore unknown DNS record types
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
36 fixes to name decoding
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
37 works alongside other processes using port 5353 (e.g. Mac OS X)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
38 tested against Mac OS X 10.3.2's mDNSResponder
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
39 corrections to removal of list entries for service browser"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
40
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
41 """0.10 update - Jonathon Paisley contributed these corrections:
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
42 always multicast replies, even when query is unicast
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
43 correct a pointer encoding problem
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
44 can now write records in any order
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
45 traceback shown on failure
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
46 better TXT record parsing
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
47 server is now separate from name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
48 can cancel a service browser
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
49
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
50 modified some unit tests to accommodate these changes"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
51
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
52 """0.09 update - remove all records on service unregistration
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
53 fix DOS security problem with readName"""
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
54
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
55 """0.08 update - changed licensing to LGPL"""
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
56
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
57 """0.07 update - faster shutdown on engine
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
58 pointer encoding of outgoing names
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
59 ServiceBrowser now works
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
60 new unit tests"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
61
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
62 """0.06 update - small improvements with unit tests
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
63 added defined exception types
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
64 new style objects
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
65 fixed hostname/interface problem
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
66 fixed socket timeout problem
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
67 fixed addServiceListener() typo bug
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
68 using select() for socket reads
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
69 tested on Debian unstable with Python 2.2.2"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
70
17424
e7cfe3587ea4 fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents: 15782
diff changeset
71 """0.05 update - ensure case insensitivity on domain names
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
72 support for unicast DNS queries"""
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
73
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
74 """0.04 update - added some unit tests
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
75 added __ne__ adjuncts where required
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
76 ensure names end in '.local.'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
77 timeout on receiving socket for clean shutdown"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
78
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
79 __author__ = "Paul Scott-Murphy"
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
80 __email__ = "paul at scott dash murphy dot com"
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
81 __version__ = "0.12"
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
82
34447
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
83 import errno
28422
e2c6092ad422 zeroconf: replace reduce+add with itertools.chain
timeless <timeless@mozdev.org>
parents: 28421
diff changeset
84 import itertools
28296
a73394e7b47c zeroconf: use absolute_import
timeless <timeless@mozdev.org>
parents: 28295
diff changeset
85 import select
a73394e7b47c zeroconf: use absolute_import
timeless <timeless@mozdev.org>
parents: 28295
diff changeset
86 import socket
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
87 import string
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
88 import struct
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
89 import threading
28296
a73394e7b47c zeroconf: use absolute_import
timeless <timeless@mozdev.org>
parents: 28295
diff changeset
90 import time
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
91 import traceback
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
92
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
93 __all__ = ["Zeroconf", "ServiceInfo", "ServiceBrowser"]
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
95 # hook for threads
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
96
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
97 globals()['_GLOBAL_DONE'] = 0
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
98
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
99 # Some timing constants
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
100
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
101 _UNREGISTER_TIME = 125
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
102 _CHECK_TIME = 175
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
103 _REGISTER_TIME = 225
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
104 _LISTENER_TIME = 200
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
105 _BROWSER_TIME = 500
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
106
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
107 # Some DNS constants
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
108
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
109 _MDNS_ADDR = '224.0.0.251'
28297
f6d07520c665 zeroconf: omit semicolons
timeless <timeless@mozdev.org>
parents: 28296
diff changeset
110 _MDNS_PORT = 5353
f6d07520c665 zeroconf: omit semicolons
timeless <timeless@mozdev.org>
parents: 28296
diff changeset
111 _DNS_PORT = 53
f6d07520c665 zeroconf: omit semicolons
timeless <timeless@mozdev.org>
parents: 28296
diff changeset
112 _DNS_TTL = 60 * 60 # one hour default TTL
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
113
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
114 _MAX_MSG_TYPICAL = 1460 # unused
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
115 _MAX_MSG_ABSOLUTE = 8972
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
116
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
117 _FLAGS_QR_MASK = 0x8000 # query response mask
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
118 _FLAGS_QR_QUERY = 0x0000 # query
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
119 _FLAGS_QR_RESPONSE = 0x8000 # response
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
120
17476
210acc861c40 spelling: Authoritative
timeless@mozdev.org
parents: 15782
diff changeset
121 _FLAGS_AA = 0x0400 # Authoritative answer
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
122 _FLAGS_TC = 0x0200 # Truncated
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
123 _FLAGS_RD = 0x0100 # Recursion desired
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
124 _FLAGS_RA = 0x8000 # Recursion available
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
125
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
126 _FLAGS_Z = 0x0040 # Zero
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
127 _FLAGS_AD = 0x0020 # Authentic data
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
128 _FLAGS_CD = 0x0010 # Checking disabled
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
129
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
130 _CLASS_IN = 1
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
131 _CLASS_CS = 2
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
132 _CLASS_CH = 3
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
133 _CLASS_HS = 4
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
134 _CLASS_NONE = 254
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
135 _CLASS_ANY = 255
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
136 _CLASS_MASK = 0x7FFF
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
137 _CLASS_UNIQUE = 0x8000
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
138
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
139 _TYPE_A = 1
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
140 _TYPE_NS = 2
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
141 _TYPE_MD = 3
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
142 _TYPE_MF = 4
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
143 _TYPE_CNAME = 5
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
144 _TYPE_SOA = 6
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
145 _TYPE_MB = 7
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
146 _TYPE_MG = 8
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
147 _TYPE_MR = 9
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
148 _TYPE_NULL = 10
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
149 _TYPE_WKS = 11
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
150 _TYPE_PTR = 12
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
151 _TYPE_HINFO = 13
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
152 _TYPE_MINFO = 14
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
153 _TYPE_MX = 15
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
154 _TYPE_TXT = 16
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
155 _TYPE_AAAA = 28
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
156 _TYPE_SRV = 33
27637
b502138f5faa cleanup: remove superfluous space after space after equals (python)
timeless <timeless@mozdev.org>
parents: 17537
diff changeset
157 _TYPE_ANY = 255
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
158
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
159 # Mapping constants to names
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
160
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
161 _CLASSES = { _CLASS_IN : "in",
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
162 _CLASS_CS : "cs",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
163 _CLASS_CH : "ch",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
164 _CLASS_HS : "hs",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
165 _CLASS_NONE : "none",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
166 _CLASS_ANY : "any" }
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
167
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
168 _TYPES = { _TYPE_A : "a",
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
169 _TYPE_NS : "ns",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
170 _TYPE_MD : "md",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
171 _TYPE_MF : "mf",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
172 _TYPE_CNAME : "cname",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
173 _TYPE_SOA : "soa",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
174 _TYPE_MB : "mb",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
175 _TYPE_MG : "mg",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
176 _TYPE_MR : "mr",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
177 _TYPE_NULL : "null",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
178 _TYPE_WKS : "wks",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
179 _TYPE_PTR : "ptr",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
180 _TYPE_HINFO : "hinfo",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
181 _TYPE_MINFO : "minfo",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
182 _TYPE_MX : "mx",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
183 _TYPE_TXT : "txt",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
184 _TYPE_AAAA : "quada",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
185 _TYPE_SRV : "srv",
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
186 _TYPE_ANY : "any" }
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
187
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
188 # utility functions
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
189
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
190 def currentTimeMillis():
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
191 """Current system time in milliseconds"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
192 return time.time() * 1000
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
193
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
194 # Exceptions
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
195
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
196 class NonLocalNameException(Exception):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
197 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
198
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
199 class NonUniqueNameException(Exception):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
200 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
201
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
202 class NamePartTooLongException(Exception):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
203 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
204
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
205 class AbstractMethodException(Exception):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
206 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
207
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
208 class BadTypeInNameException(Exception):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
209 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
210
11435
7c58cde598fe zeroconf: Use BadDomainName exception instead of string exceptions
Javi Merino <cibervicho@gmail.com>
parents: 10514
diff changeset
211 class BadDomainName(Exception):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
212 def __init__(self, pos):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
213 Exception.__init__(self, "at position %s" % pos)
11435
7c58cde598fe zeroconf: Use BadDomainName exception instead of string exceptions
Javi Merino <cibervicho@gmail.com>
parents: 10514
diff changeset
214
7c58cde598fe zeroconf: Use BadDomainName exception instead of string exceptions
Javi Merino <cibervicho@gmail.com>
parents: 10514
diff changeset
215 class BadDomainNameCircular(BadDomainName):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
216 pass
11435
7c58cde598fe zeroconf: Use BadDomainName exception instead of string exceptions
Javi Merino <cibervicho@gmail.com>
parents: 10514
diff changeset
217
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
218 # implementation classes
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
219
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
220 class DNSEntry(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
221 """A DNS entry"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
222
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
223 def __init__(self, name, type, clazz):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
224 self.key = string.lower(name)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
225 self.name = name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
226 self.type = type
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
227 self.clazz = clazz & _CLASS_MASK
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
228 self.unique = (clazz & _CLASS_UNIQUE) != 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
229
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
230 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
231 """Equality test on name, type, and class"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
232 if isinstance(other, DNSEntry):
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
233 return (self.name == other.name and self.type == other.type and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
234 self.clazz == other.clazz)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
235 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
236
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
237 def __ne__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
238 """Non-equality test"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
239 return not self.__eq__(other)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
240
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
241 def getClazz(self, clazz):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
242 """Class accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
243 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
244 return _CLASSES[clazz]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
245 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
246 return "?(%s)" % (clazz)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
247
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
248 def getType(self, type):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
249 """Type accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
250 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
251 return _TYPES[type]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
252 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
253 return "?(%s)" % (type)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
254
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
255 def toString(self, hdr, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
256 """String representation with additional information"""
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
257 result = ("%s[%s,%s" %
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
258 (hdr, self.getType(self.type), self.getClazz(self.clazz)))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
259 if self.unique:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
260 result += "-unique,"
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
261 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
262 result += ","
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
263 result += self.name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
264 if other is not None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
265 result += ",%s]" % (other)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
266 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
267 result += "]"
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
268 return result
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
269
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
270 class DNSQuestion(DNSEntry):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
271 """A DNS question entry"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
272
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
273 def __init__(self, name, type, clazz):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
274 if not name.endswith(".local."):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
275 raise NonLocalNameException(name)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
276 DNSEntry.__init__(self, name, type, clazz)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
277
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
278 def answeredBy(self, rec):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
279 """Returns true if the question is answered by the record"""
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
280 return (self.clazz == rec.clazz and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
281 (self.type == rec.type or self.type == _TYPE_ANY) and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
282 self.name == rec.name)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
283
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
284 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
285 """String representation"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
286 return DNSEntry.toString(self, "question", None)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
287
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
288
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
289 class DNSRecord(DNSEntry):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
290 """A DNS record - like a DNS entry, but has a TTL"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
291
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
292 def __init__(self, name, type, clazz, ttl):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
293 DNSEntry.__init__(self, name, type, clazz)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
294 self.ttl = ttl
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
295 self.created = currentTimeMillis()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
296
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
297 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
298 """Tests equality as per DNSRecord"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
299 if isinstance(other, DNSRecord):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
300 return DNSEntry.__eq__(self, other)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
301 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
302
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
303 def suppressedBy(self, msg):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
304 """Returns true if any answer in a message can suffice for the
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
305 information held in this record."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
306 for record in msg.answers:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
307 if self.suppressedByAnswer(record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
308 return 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
309 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
310
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
311 def suppressedByAnswer(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
312 """Returns true if another record has same name, type and class,
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
313 and if its TTL is at least half of this record's."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
314 if self == other and other.ttl > (self.ttl / 2):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
315 return 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
316 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
317
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
318 def getExpirationTime(self, percent):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
319 """Returns the time at which this record will have expired
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
320 by a certain percentage."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
321 return self.created + (percent * self.ttl * 10)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
322
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
323 def getRemainingTTL(self, now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
324 """Returns the remaining TTL in seconds."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
325 return max(0, (self.getExpirationTime(100) - now) / 1000)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
326
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
327 def isExpired(self, now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
328 """Returns true if this record has expired."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
329 return self.getExpirationTime(100) <= now
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
330
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
331 def isStale(self, now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
332 """Returns true if this record is at least half way expired."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
333 return self.getExpirationTime(50) <= now
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
334
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
335 def resetTTL(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
336 """Sets this record's TTL and created time to that of
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
337 another record."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
338 self.created = other.created
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
339 self.ttl = other.ttl
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
340
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
341 def write(self, out):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
342 """Abstract method"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
343 raise AbstractMethodException
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
344
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
345 def toString(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
346 """String representation with additional information"""
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
347 arg = ("%s/%s,%s" %
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
348 (self.ttl, self.getRemainingTTL(currentTimeMillis()), other))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
349 return DNSEntry.toString(self, "record", arg)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
350
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
351 class DNSAddress(DNSRecord):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
352 """A DNS address record"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
353
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
354 def __init__(self, name, type, clazz, ttl, address):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
355 DNSRecord.__init__(self, name, type, clazz, ttl)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
356 self.address = address
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
357
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
358 def write(self, out):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
359 """Used in constructing an outgoing packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
360 out.writeString(self.address, len(self.address))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
361
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
362 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
363 """Tests equality on address"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
364 if isinstance(other, DNSAddress):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
365 return self.address == other.address
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
366 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
367
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
368 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
369 """String representation"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
370 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
371 return socket.inet_ntoa(self.address)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
372 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
373 return self.address
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
374
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
375 class DNSHinfo(DNSRecord):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
376 """A DNS host information record"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
377
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
378 def __init__(self, name, type, clazz, ttl, cpu, os):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
379 DNSRecord.__init__(self, name, type, clazz, ttl)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
380 self.cpu = cpu
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
381 self.os = os
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
382
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
383 def write(self, out):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
384 """Used in constructing an outgoing packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
385 out.writeString(self.cpu, len(self.cpu))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
386 out.writeString(self.os, len(self.os))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
387
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
388 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
389 """Tests equality on cpu and os"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
390 if isinstance(other, DNSHinfo):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
391 return self.cpu == other.cpu and self.os == other.os
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
392 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
393
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
394 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
395 """String representation"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
396 return self.cpu + " " + self.os
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
397
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
398 class DNSPointer(DNSRecord):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
399 """A DNS pointer record"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
400
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
401 def __init__(self, name, type, clazz, ttl, alias):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
402 DNSRecord.__init__(self, name, type, clazz, ttl)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
403 self.alias = alias
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
404
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
405 def write(self, out):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
406 """Used in constructing an outgoing packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
407 out.writeName(self.alias)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
408
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
409 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
410 """Tests equality on alias"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
411 if isinstance(other, DNSPointer):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
412 return self.alias == other.alias
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
413 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
414
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
415 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
416 """String representation"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
417 return self.toString(self.alias)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
418
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
419 class DNSText(DNSRecord):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
420 """A DNS text record"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
421
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
422 def __init__(self, name, type, clazz, ttl, text):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
423 DNSRecord.__init__(self, name, type, clazz, ttl)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
424 self.text = text
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
425
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
426 def write(self, out):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
427 """Used in constructing an outgoing packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
428 out.writeString(self.text, len(self.text))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
429
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
430 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
431 """Tests equality on text"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
432 if isinstance(other, DNSText):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
433 return self.text == other.text
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
434 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
435
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
436 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
437 """String representation"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
438 if len(self.text) > 10:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
439 return self.toString(self.text[:7] + "...")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
440 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
441 return self.toString(self.text)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
442
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
443 class DNSService(DNSRecord):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
444 """A DNS service record"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
445
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
446 def __init__(self, name, type, clazz, ttl, priority, weight, port, server):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
447 DNSRecord.__init__(self, name, type, clazz, ttl)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
448 self.priority = priority
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
449 self.weight = weight
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
450 self.port = port
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
451 self.server = server
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
452
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
453 def write(self, out):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
454 """Used in constructing an outgoing packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
455 out.writeShort(self.priority)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
456 out.writeShort(self.weight)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
457 out.writeShort(self.port)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
458 out.writeName(self.server)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
459
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
460 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
461 """Tests equality on priority, weight, port and server"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
462 if isinstance(other, DNSService):
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
463 return (self.priority == other.priority and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
464 self.weight == other.weight and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
465 self.port == other.port and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
466 self.server == other.server)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
467 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
468
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
469 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
470 """String representation"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
471 return self.toString("%s:%s" % (self.server, self.port))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
472
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
473 class DNSIncoming(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
474 """Object representation of an incoming DNS packet"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
475
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
476 def __init__(self, data):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
477 """Constructor from string holding bytes of packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
478 self.offset = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
479 self.data = data
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
480 self.questions = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
481 self.answers = []
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
482 self.numquestions = 0
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
483 self.numanswers = 0
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
484 self.numauthorities = 0
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
485 self.numadditionals = 0
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
486
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
487 self.readHeader()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
488 self.readQuestions()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
489 self.readOthers()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
490
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
491 def readHeader(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
492 """Reads header portion of packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
493 format = '!HHHHHH'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
494 length = struct.calcsize(format)
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
495 info = struct.unpack(format,
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
496 self.data[self.offset:self.offset + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
497 self.offset += length
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
498
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
499 self.id = info[0]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
500 self.flags = info[1]
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
501 self.numquestions = info[2]
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
502 self.numanswers = info[3]
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
503 self.numauthorities = info[4]
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
504 self.numadditionals = info[5]
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
505
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
506 def readQuestions(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
507 """Reads questions section of packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
508 format = '!HH'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
509 length = struct.calcsize(format)
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
510 for i in range(0, self.numquestions):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
511 name = self.readName()
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
512 info = struct.unpack(format,
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
513 self.data[self.offset:self.offset + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
514 self.offset += length
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
515
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
516 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
517 question = DNSQuestion(name, info[0], info[1])
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
518 self.questions.append(question)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
519 except NonLocalNameException:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
520 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
521
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
522 def readInt(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
523 """Reads an integer from the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
524 format = '!I'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
525 length = struct.calcsize(format)
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
526 info = struct.unpack(format,
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
527 self.data[self.offset:self.offset + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
528 self.offset += length
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
529 return info[0]
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
530
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
531 def readCharacterString(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
532 """Reads a character string from the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
533 length = ord(self.data[self.offset])
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
534 self.offset += 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
535 return self.readString(length)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
536
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
537 def readString(self, len):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
538 """Reads a string of a given length from the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
539 format = '!' + str(len) + 's'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
540 length = struct.calcsize(format)
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
541 info = struct.unpack(format,
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
542 self.data[self.offset:self.offset + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
543 self.offset += length
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
544 return info[0]
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
545
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
546 def readUnsignedShort(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
547 """Reads an unsigned short from the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
548 format = '!H'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
549 length = struct.calcsize(format)
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
550 info = struct.unpack(format,
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
551 self.data[self.offset:self.offset + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
552 self.offset += length
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
553 return info[0]
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
554
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
555 def readOthers(self):
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
556 """Reads answers, authorities and additionals section of the packet"""
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
557 format = '!HHiH'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
558 length = struct.calcsize(format)
28504
3c90090320ad zeroconf: remove leftover camelcase identifier
Martin von Zweigbergk <martinvonz@google.com>
parents: 28422
diff changeset
559 n = self.numanswers + self.numauthorities + self.numadditionals
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
560 for i in range(0, n):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
561 domain = self.readName()
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
562 info = struct.unpack(format,
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
563 self.data[self.offset:self.offset + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
564 self.offset += length
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
565
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
566 rec = None
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
567 if info[0] == _TYPE_A:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
568 rec = DNSAddress(domain, info[0], info[1], info[2],
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
569 self.readString(4))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
570 elif info[0] == _TYPE_CNAME or info[0] == _TYPE_PTR:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
571 rec = DNSPointer(domain, info[0], info[1], info[2],
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
572 self.readName())
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
573 elif info[0] == _TYPE_TXT:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
574 rec = DNSText(domain, info[0], info[1], info[2],
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
575 self.readString(info[3]))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
576 elif info[0] == _TYPE_SRV:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
577 rec = DNSService(domain, info[0], info[1], info[2],
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
578 self.readUnsignedShort(),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
579 self.readUnsignedShort(),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
580 self.readUnsignedShort(),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
581 self.readName())
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
582 elif info[0] == _TYPE_HINFO:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
583 rec = DNSHinfo(domain, info[0], info[1], info[2],
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
584 self.readCharacterString(),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
585 self.readCharacterString())
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
586 elif info[0] == _TYPE_AAAA:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
587 rec = DNSAddress(domain, info[0], info[1], info[2],
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
588 self.readString(16))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
589 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
590 # Try to ignore types we don't know about
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
591 # this may mean the rest of the name is
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
592 # unable to be parsed, and may show errors
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
593 # so this is left for debugging. New types
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
594 # encountered need to be parsed properly.
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
595 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
596 #print "UNKNOWN TYPE = " + str(info[0])
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
597 #raise BadTypeInNameException
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
598 self.offset += info[3]
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
599
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
600 if rec is not None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
601 self.answers.append(rec)
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
602
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
603 def isQuery(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
604 """Returns true if this is a query"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
605 return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_QUERY
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
606
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
607 def isResponse(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
608 """Returns true if this is a response"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
609 return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_RESPONSE
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
610
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
611 def readUTF(self, offset, len):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
612 """Reads a UTF-8 string of a given length from the packet"""
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
613 return self.data[offset:offset + len].decode('utf-8')
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
614
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
615 def readName(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
616 """Reads a domain name from the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
617 result = ''
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
618 off = self.offset
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
619 next = -1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
620 first = off
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
621
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
622 while True:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
623 len = ord(self.data[off])
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
624 off += 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
625 if len == 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
626 break
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
627 t = len & 0xC0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
628 if t == 0x00:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
629 result = ''.join((result, self.readUTF(off, len) + '.'))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
630 off += len
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
631 elif t == 0xC0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
632 if next < 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
633 next = off + 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
634 off = ((len & 0x3F) << 8) | ord(self.data[off])
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
635 if off >= first:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
636 raise BadDomainNameCircular(off)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
637 first = off
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
638 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
639 raise BadDomainName(off)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
640
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
641 if next >= 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
642 self.offset = next
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
643 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
644 self.offset = off
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
645
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
646 return result
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
647
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
648
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
649 class DNSOutgoing(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
650 """Object representation of an outgoing packet"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
651
28302
e96a3ae025ed zeroconf: remove whitespace around = for named parameters
timeless <timeless@mozdev.org>
parents: 28301
diff changeset
652 def __init__(self, flags, multicast=1):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
653 self.finished = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
654 self.id = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
655 self.multicast = multicast
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
656 self.flags = flags
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
657 self.names = {}
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
658 self.data = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
659 self.size = 12
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
660
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
661 self.questions = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
662 self.answers = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
663 self.authorities = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
664 self.additionals = []
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
665
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
666 def addQuestion(self, record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
667 """Adds a question"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
668 self.questions.append(record)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
669
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
670 def addAnswer(self, inp, record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
671 """Adds an answer"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
672 if not record.suppressedBy(inp):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
673 self.addAnswerAtTime(record, 0)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
674
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
675 def addAnswerAtTime(self, record, now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
676 """Adds an answer if if does not expire by a certain time"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
677 if record is not None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
678 if now == 0 or not record.isExpired(now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
679 self.answers.append((record, now))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
680
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
681 def addAuthoritativeAnswer(self, record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
682 """Adds an authoritative answer"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
683 self.authorities.append(record)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
684
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
685 def addAdditionalAnswer(self, record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
686 """Adds an additional answer"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
687 self.additionals.append(record)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
688
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
689 def writeByte(self, value):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
690 """Writes a single byte to the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
691 format = '!c'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
692 self.data.append(struct.pack(format, chr(value)))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
693 self.size += 1
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
694
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
695 def insertShort(self, index, value):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
696 """Inserts an unsigned short in a certain position in the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
697 format = '!H'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
698 self.data.insert(index, struct.pack(format, value))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
699 self.size += 2
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
700
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
701 def writeShort(self, value):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
702 """Writes an unsigned short to the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
703 format = '!H'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
704 self.data.append(struct.pack(format, value))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
705 self.size += 2
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
706
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
707 def writeInt(self, value):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
708 """Writes an unsigned integer to the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
709 format = '!I'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
710 self.data.append(struct.pack(format, int(value)))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
711 self.size += 4
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
712
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
713 def writeString(self, value, length):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
714 """Writes a string to the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
715 format = '!' + str(length) + 's'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
716 self.data.append(struct.pack(format, value))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
717 self.size += length
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
718
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
719 def writeUTF(self, s):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
720 """Writes a UTF-8 string of a given length to the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
721 utfstr = s.encode('utf-8')
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
722 length = len(utfstr)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
723 if length > 64:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
724 raise NamePartTooLongException
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
725 self.writeByte(length)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
726 self.writeString(utfstr, length)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
727
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
728 def writeName(self, name):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
729 """Writes a domain name to the packet"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
730
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
731 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
732 # Find existing instance of this name in packet
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
733 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
734 index = self.names[name]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
735 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
736 # No record of this name already, so write it
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
737 # out as normal, recording the location of the name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
738 # for future pointers to it.
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
739 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
740 self.names[name] = self.size
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
741 parts = name.split('.')
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
742 if parts[-1] == '':
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
743 parts = parts[:-1]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
744 for part in parts:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
745 self.writeUTF(part)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
746 self.writeByte(0)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
747 return
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
748
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
749 # An index was found, so write a pointer to it
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
750 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
751 self.writeByte((index >> 8) | 0xC0)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
752 self.writeByte(index)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
753
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
754 def writeQuestion(self, question):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
755 """Writes a question to the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
756 self.writeName(question.name)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
757 self.writeShort(question.type)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
758 self.writeShort(question.clazz)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
759
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
760 def writeRecord(self, record, now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
761 """Writes a record (answer, authoritative answer, additional) to
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
762 the packet"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
763 self.writeName(record.name)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
764 self.writeShort(record.type)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
765 if record.unique and self.multicast:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
766 self.writeShort(record.clazz | _CLASS_UNIQUE)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
767 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
768 self.writeShort(record.clazz)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
769 if now == 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
770 self.writeInt(record.ttl)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
771 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
772 self.writeInt(record.getRemainingTTL(now))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
773 index = len(self.data)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
774 # Adjust size for the short we will write before this record
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
775 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
776 self.size += 2
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
777 record.write(self)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
778 self.size -= 2
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
779
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
780 length = len(''.join(self.data[index:]))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
781 self.insertShort(index, length) # Here is the short we adjusted for
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
782
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
783 def packet(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
784 """Returns a string containing the packet's bytes
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
785
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
786 No further parts should be added to the packet once this
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
787 is done."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
788 if not self.finished:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
789 self.finished = 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
790 for question in self.questions:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
791 self.writeQuestion(question)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
792 for answer, time_ in self.answers:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
793 self.writeRecord(answer, time_)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
794 for authority in self.authorities:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
795 self.writeRecord(authority, 0)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
796 for additional in self.additionals:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
797 self.writeRecord(additional, 0)
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
798
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
799 self.insertShort(0, len(self.additionals))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
800 self.insertShort(0, len(self.authorities))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
801 self.insertShort(0, len(self.answers))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
802 self.insertShort(0, len(self.questions))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
803 self.insertShort(0, self.flags)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
804 if self.multicast:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
805 self.insertShort(0, 0)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
806 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
807 self.insertShort(0, self.id)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
808 return ''.join(self.data)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
809
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
810
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
811 class DNSCache(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
812 """A cache of DNS entries"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
813
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
814 def __init__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
815 self.cache = {}
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
816
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
817 def add(self, entry):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
818 """Adds an entry"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
819 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
820 list = self.cache[entry.key]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
821 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
822 list = self.cache[entry.key] = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
823 list.append(entry)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
824
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
825 def remove(self, entry):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
826 """Removes an entry"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
827 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
828 list = self.cache[entry.key]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
829 list.remove(entry)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
830 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
831 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
832
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
833 def get(self, entry):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
834 """Gets an entry by key. Will return None if there is no
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
835 matching entry."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
836 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
837 list = self.cache[entry.key]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
838 return list[list.index(entry)]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
839 except (KeyError, ValueError):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
840 return None
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
841
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
842 def getByDetails(self, name, type, clazz):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
843 """Gets an entry by details. Will return None if there is
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
844 no matching entry."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
845 entry = DNSEntry(name, type, clazz)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
846 return self.get(entry)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
847
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
848 def entriesWithName(self, name):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
849 """Returns a list of entries whose key matches the name."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
850 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
851 return self.cache[name]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
852 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
853 return []
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
854
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
855 def entries(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
856 """Returns a list of all entries"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
857 try:
28422
e2c6092ad422 zeroconf: replace reduce+add with itertools.chain
timeless <timeless@mozdev.org>
parents: 28421
diff changeset
858 return list(itertools.chain.from_iterable(self.cache.values()))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
859 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
860 return []
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
861
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
862
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
863 class Engine(threading.Thread):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
864 """An engine wraps read access to sockets, allowing objects that
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
865 need to receive data from sockets to be called back when the
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
866 sockets are ready.
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
867
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
868 A reader needs a handle_read() method, which is called when the socket
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
869 it is interested in is ready for reading.
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
870
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
871 Writers are not implemented here, because we only send short
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
872 packets.
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
873 """
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
874
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
875 def __init__(self, zeroconf):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
876 threading.Thread.__init__(self)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
877 self.zeroconf = zeroconf
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
878 self.readers = {} # maps socket to reader
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
879 self.timeout = 5
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
880 self.condition = threading.Condition()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
881 self.start()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
882
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
883 def run(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
884 while not globals()['_GLOBAL_DONE']:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
885 rs = self.getReaders()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
886 if len(rs) == 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
887 # No sockets to manage, but we wait for the timeout
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
888 # or addition of a socket
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
889 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
890 self.condition.acquire()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
891 self.condition.wait(self.timeout)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
892 self.condition.release()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
893 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
894 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
895 rr, wr, er = select.select(rs, [], [], self.timeout)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
896 for sock in rr:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
897 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
898 self.readers[sock].handle_read()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
899 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
900 if not globals()['_GLOBAL_DONE']:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
901 traceback.print_exc()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
902 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
903 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
904
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
905 def getReaders(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
906 self.condition.acquire()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
907 result = self.readers.keys()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
908 self.condition.release()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
909 return result
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
910
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
911 def addReader(self, reader, socket):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
912 self.condition.acquire()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
913 self.readers[socket] = reader
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
914 self.condition.notify()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
915 self.condition.release()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
916
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
917 def delReader(self, socket):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
918 self.condition.acquire()
28301
fd8a4d2d6541 zeroconf: del is not a function
timeless <timeless@mozdev.org>
parents: 28300
diff changeset
919 del self.readers[socket]
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
920 self.condition.notify()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
921 self.condition.release()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
922
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
923 def notify(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
924 self.condition.acquire()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
925 self.condition.notify()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
926 self.condition.release()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
927
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
928 class Listener(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
929 """A Listener is used by this module to listen on the multicast
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
930 group to which DNS messages are sent, allowing the implementation
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
931 to cache information as it arrives.
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
932
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
933 It requires registration with an Engine object in order to have
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
934 the read() method called when a socket is available for reading."""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
935
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
936 def __init__(self, zeroconf):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
937 self.zeroconf = zeroconf
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
938 self.zeroconf.engine.addReader(self, self.zeroconf.socket)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
939
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
940 def handle_read(self):
34447
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
941 data = addr = port = None
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
942 sock = self.zeroconf.socket
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
943 try:
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
944 data, (addr, port) = sock.recvfrom(_MAX_MSG_ABSOLUTE)
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
945 except socket.error as e:
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
946 if e.errno == errno.EBADF:
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
947 # some other thread may close the socket
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
948 return
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
949 else:
5385b76fd1fd zeroconf: do not crash if socket being read is closed by another thread
Jun Wu <quark@fb.com>
parents: 28504
diff changeset
950 raise
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
951 self.data = data
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
952 msg = DNSIncoming(data)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
953 if msg.isQuery():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
954 # Always multicast responses
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
955 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
956 if port == _MDNS_PORT:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
957 self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
958 # If it's not a multicast query, reply via unicast
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
959 # and multicast
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
960 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
961 elif port == _DNS_PORT:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
962 self.zeroconf.handleQuery(msg, addr, port)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
963 self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
964 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
965 self.zeroconf.handleResponse(msg)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
966
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
967
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
968 class Reaper(threading.Thread):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
969 """A Reaper is used by this module to remove cache entries that
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
970 have expired."""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
971
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
972 def __init__(self, zeroconf):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
973 threading.Thread.__init__(self)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
974 self.zeroconf = zeroconf
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
975 self.start()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
976
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
977 def run(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
978 while True:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
979 self.zeroconf.wait(10 * 1000)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
980 if globals()['_GLOBAL_DONE']:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
981 return
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
982 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
983 for record in self.zeroconf.cache.entries():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
984 if record.isExpired(now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
985 self.zeroconf.updateRecord(now, record)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
986 self.zeroconf.cache.remove(record)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
987
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
988
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
989 class ServiceBrowser(threading.Thread):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
990 """Used to browse for a service of a specific type.
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
991
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
992 The listener object will have its addService() and
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
993 removeService() methods called when this browser
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
994 discovers changes in the services availability."""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
995
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
996 def __init__(self, zeroconf, type, listener):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
997 """Creates a browser for a specific type"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
998 threading.Thread.__init__(self)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
999 self.zeroconf = zeroconf
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1000 self.type = type
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1001 self.listener = listener
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1002 self.services = {}
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1003 self.nexttime = currentTimeMillis()
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1004 self.delay = _BROWSER_TIME
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1005 self.list = []
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1006
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1007 self.done = 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1008
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1009 self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1010 _CLASS_IN))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1011 self.start()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1012
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1013 def updateRecord(self, zeroconf, now, record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1014 """Callback invoked by Zeroconf when new information arrives.
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1015
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1016 Updates information required by browser in the Zeroconf cache."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1017 if record.type == _TYPE_PTR and record.name == self.type:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1018 expired = record.isExpired(now)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1019 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1020 oldrecord = self.services[record.alias.lower()]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1021 if not expired:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1022 oldrecord.resetTTL(record)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1023 else:
28301
fd8a4d2d6541 zeroconf: del is not a function
timeless <timeless@mozdev.org>
parents: 28300
diff changeset
1024 del self.services[record.alias.lower()]
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1025 callback = (lambda x:
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1026 self.listener.removeService(x, self.type, record.alias))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1027 self.list.append(callback)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1028 return
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1029 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1030 if not expired:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1031 self.services[record.alias.lower()] = record
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1032 callback = (lambda x:
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1033 self.listener.addService(x, self.type, record.alias))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1034 self.list.append(callback)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1035
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1036 expires = record.getExpirationTime(75)
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1037 if expires < self.nexttime:
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1038 self.nexttime = expires
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1039
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1040 def cancel(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1041 self.done = 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1042 self.zeroconf.notifyAll()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1043
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1044 def run(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1045 while True:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1046 event = None
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1047 now = currentTimeMillis()
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1048 if len(self.list) == 0 and self.nexttime > now:
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1049 self.zeroconf.wait(self.nexttime - now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1050 if globals()['_GLOBAL_DONE'] or self.done:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1051 return
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1052 now = currentTimeMillis()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1053
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1054 if self.nexttime <= now:
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1055 out = DNSOutgoing(_FLAGS_QR_QUERY)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1056 out.addQuestion(DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1057 for record in self.services.values():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1058 if not record.isExpired(now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1059 out.addAnswerAtTime(record, now)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1060 self.zeroconf.send(out)
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1061 self.nexttime = now + self.delay
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1062 self.delay = min(20 * 1000, self.delay * 2)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1063
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1064 if len(self.list) > 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1065 event = self.list.pop(0)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1066
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1067 if event is not None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1068 event(self.zeroconf)
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1069
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1070
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1071 class ServiceInfo(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1072 """Service information"""
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1073
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1074 def __init__(self, type, name, address=None, port=None, weight=0,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1075 priority=0, properties=None, server=None):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1076 """Create a service description.
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1077
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1078 type: fully qualified service type name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1079 name: fully qualified service name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1080 address: IP address as unsigned short, network byte order
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1081 port: port that the service runs on
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1082 weight: weight of the service
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1083 priority: priority of the service
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1084 properties: dictionary of properties (or a string holding the bytes for
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1085 the text field)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1086 server: fully qualified name for service host (defaults to name)"""
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1087
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1088 if not name.endswith(type):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1089 raise BadTypeInNameException
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1090 self.type = type
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1091 self.name = name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1092 self.address = address
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1093 self.port = port
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1094 self.weight = weight
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1095 self.priority = priority
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1096 if server:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1097 self.server = server
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1098 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1099 self.server = name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1100 self.setProperties(properties)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1101
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1102 def setProperties(self, properties):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1103 """Sets properties and text of this info from a dictionary"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1104 if isinstance(properties, dict):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1105 self.properties = properties
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1106 list = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1107 result = ''
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1108 for key in properties:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1109 value = properties[key]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1110 if value is None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1111 suffix = ''
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1112 elif isinstance(value, str):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1113 suffix = value
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1114 elif isinstance(value, int):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1115 if value:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1116 suffix = 'true'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1117 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1118 suffix = 'false'
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1119 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1120 suffix = ''
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1121 list.append('='.join((key, suffix)))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1122 for item in list:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1123 result = ''.join((result, struct.pack('!c', chr(len(item))),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1124 item))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1125 self.text = result
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1126 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1127 self.text = properties
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1128
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1129 def setText(self, text):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1130 """Sets properties and text given a text field"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1131 self.text = text
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1132 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1133 result = {}
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1134 end = len(text)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1135 index = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1136 strs = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1137 while index < end:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1138 length = ord(text[index])
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1139 index += 1
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1140 strs.append(text[index:index + length])
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1141 index += length
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1142
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1143 for s in strs:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1144 eindex = s.find('=')
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1145 if eindex == -1:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1146 # No equals sign at all
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1147 key = s
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1148 value = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1149 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1150 key = s[:eindex]
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1151 value = s[eindex + 1:]
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1152 if value == 'true':
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1153 value = 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1154 elif value == 'false' or not value:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1155 value = 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1156
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1157 # Only update non-existent properties
28420
d03b7800672c zeroconf: compare singleton using is
timeless <timeless@mozdev.org>
parents: 28419
diff changeset
1158 if key and result.get(key) is None:
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1159 result[key] = value
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1160
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1161 self.properties = result
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1162 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1163 traceback.print_exc()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1164 self.properties = None
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1165
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1166 def getType(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1167 """Type accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1168 return self.type
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1169
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1170 def getName(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1171 """Name accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1172 if self.type is not None and self.name.endswith("." + self.type):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1173 return self.name[:len(self.name) - len(self.type) - 1]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1174 return self.name
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1175
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1176 def getAddress(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1177 """Address accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1178 return self.address
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1179
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1180 def getPort(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1181 """Port accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1182 return self.port
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1183
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1184 def getPriority(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1185 """Priority accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1186 return self.priority
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1187
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1188 def getWeight(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1189 """Weight accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1190 return self.weight
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1191
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1192 def getProperties(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1193 """Properties accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1194 return self.properties
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1195
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1196 def getText(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1197 """Text accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1198 return self.text
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1199
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1200 def getServer(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1201 """Server accessor"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1202 return self.server
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1203
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1204 def updateRecord(self, zeroconf, now, record):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1205 """Updates service information from a DNS record"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1206 if record is not None and not record.isExpired(now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1207 if record.type == _TYPE_A:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1208 #if record.name == self.name:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1209 if record.name == self.server:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1210 self.address = record.address
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1211 elif record.type == _TYPE_SRV:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1212 if record.name == self.name:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1213 self.server = record.server
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1214 self.port = record.port
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1215 self.weight = record.weight
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1216 self.priority = record.priority
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1217 #self.address = None
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1218 self.updateRecord(zeroconf, now,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1219 zeroconf.cache.getByDetails(self.server,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1220 _TYPE_A, _CLASS_IN))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1221 elif record.type == _TYPE_TXT:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1222 if record.name == self.name:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1223 self.setText(record.text)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1224
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1225 def request(self, zeroconf, timeout):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1226 """Returns true if the service could be discovered on the
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1227 network, and updates this object with details discovered.
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1228 """
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1229 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1230 delay = _LISTENER_TIME
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1231 next = now + delay
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1232 last = now + timeout
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1233 result = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1234 try:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1235 zeroconf.addListener(self, DNSQuestion(self.name, _TYPE_ANY,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1236 _CLASS_IN))
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1237 while (self.server is None or self.address is None or
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1238 self.text is None):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1239 if last <= now:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1240 return 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1241 if next <= now:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1242 out = DNSOutgoing(_FLAGS_QR_QUERY)
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1243 out.addQuestion(DNSQuestion(self.name, _TYPE_SRV,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1244 _CLASS_IN))
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1245 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1246 zeroconf.cache.getByDetails(self.name,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1247 _TYPE_SRV,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1248 _CLASS_IN),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1249 now)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1250 out.addQuestion(DNSQuestion(self.name, _TYPE_TXT,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1251 _CLASS_IN))
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1252 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1253 zeroconf.cache.getByDetails(self.name, _TYPE_TXT,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1254 _CLASS_IN),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1255 now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1256 if self.server is not None:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1257 out.addQuestion(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1258 DNSQuestion(self.server, _TYPE_A, _CLASS_IN))
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1259 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1260 zeroconf.cache.getByDetails(self.server, _TYPE_A,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1261 _CLASS_IN),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1262 now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1263 zeroconf.send(out)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1264 next = now + delay
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1265 delay = delay * 2
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1266
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1267 zeroconf.wait(min(next, last) - now)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1268 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1269 result = 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1270 finally:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1271 zeroconf.removeListener(self)
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1272
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1273 return result
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1274
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1275 def __eq__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1276 """Tests equality of service name"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1277 if isinstance(other, ServiceInfo):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1278 return other.name == self.name
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1279 return 0
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1280
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1281 def __ne__(self, other):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1282 """Non-equality test"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1283 return not self.__eq__(other)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1284
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1285 def __repr__(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1286 """String representation"""
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1287 result = ("service[%s,%s:%s," %
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1288 (self.name, socket.inet_ntoa(self.getAddress()), self.port))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1289 if self.text is None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1290 result += "None"
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1291 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1292 if len(self.text) < 20:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1293 result += self.text
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1294 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1295 result += self.text[:17] + "..."
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1296 result += "]"
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1297 return result
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1298
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1299
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1300 class Zeroconf(object):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1301 """Implementation of Zeroconf Multicast DNS Service Discovery
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1302
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1303 Supports registration, unregistration, queries and browsing.
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1304 """
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1305 def __init__(self, bindaddress=None):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1306 """Creates an instance of the Zeroconf class, establishing
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1307 multicast communications, listening and reaping threads."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1308 globals()['_GLOBAL_DONE'] = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1309 if bindaddress is None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1310 self.intf = socket.gethostbyname(socket.gethostname())
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1311 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1312 self.intf = bindaddress
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1313 self.group = ('', _MDNS_PORT)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1314 self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1315 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1316 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1317 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1318 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1319 # SO_REUSEADDR should be equivalent to SO_REUSEPORT for
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1320 # multicast UDP sockets (p 731, "TCP/IP Illustrated,
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1321 # Volume 2"), but some BSD-derived systems require
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1322 # SO_REUSEPORT to be specified explicitly. Also, not all
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1323 # versions of Python have SO_REUSEPORT available. So
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1324 # if you're on a BSD-based system, and haven't upgraded
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1325 # to Python 2.3 yet, you may find this library doesn't
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1326 # work as expected.
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1327 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1328 pass
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1329 self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, "\xff")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1330 self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, "\x01")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1331 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1332 self.socket.bind(self.group)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1333 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1334 # Some versions of linux raise an exception even though
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1335 # SO_REUSEADDR and SO_REUSEPORT have been set, so ignore it
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1336 pass
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1337 self.socket.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1338 socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1339
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1340 self.listeners = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1341 self.browsers = []
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1342 self.services = {}
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1343 self.servicetypes = {}
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1344
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1345 self.cache = DNSCache()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1346
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1347 self.condition = threading.Condition()
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1348
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1349 self.engine = Engine(self)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1350 self.listener = Listener(self)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1351 self.reaper = Reaper(self)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1352
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1353 def isLoopback(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1354 return self.intf.startswith("127.0.0.1")
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1355
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1356 def isLinklocal(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1357 return self.intf.startswith("169.254.")
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1358
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1359 def wait(self, timeout):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1360 """Calling thread waits for a given number of milliseconds or
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1361 until notified."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1362 self.condition.acquire()
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1363 self.condition.wait(timeout / 1000)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1364 self.condition.release()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1365
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1366 def notifyAll(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1367 """Notifies all waiting threads"""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1368 self.condition.acquire()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1369 self.condition.notifyAll()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1370 self.condition.release()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1371
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1372 def getServiceInfo(self, type, name, timeout=3000):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1373 """Returns network's service information for a particular
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1374 name and type, or None if no service matches by the timeout,
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1375 which defaults to 3 seconds."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1376 info = ServiceInfo(type, name)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1377 if info.request(self, timeout):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1378 return info
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1379 return None
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1380
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1381 def addServiceListener(self, type, listener):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1382 """Adds a listener for a particular service type. This object
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1383 will then have its updateRecord method called when information
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1384 arrives for that type."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1385 self.removeServiceListener(listener)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1386 self.browsers.append(ServiceBrowser(self, type, listener))
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1387
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1388 def removeServiceListener(self, listener):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1389 """Removes a listener from the set that is currently listening."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1390 for browser in self.browsers:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1391 if browser.listener == listener:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1392 browser.cancel()
28301
fd8a4d2d6541 zeroconf: del is not a function
timeless <timeless@mozdev.org>
parents: 28300
diff changeset
1393 del browser
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1394
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1395 def registerService(self, info, ttl=_DNS_TTL):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1396 """Registers service information to the network with a default TTL
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1397 of 60 seconds. Zeroconf will then respond to requests for
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1398 information for that service. The name of the service may be
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1399 changed if needed to make it unique on the network."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1400 self.checkService(info)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1401 self.services[info.name.lower()] = info
28421
6d72cc613fc4 zeroconf: replace has_key with in
timeless <timeless@mozdev.org>
parents: 28420
diff changeset
1402 if info.type in self.servicetypes:
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1403 self.servicetypes[info.type] += 1
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1404 else:
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1405 self.servicetypes[info.type] = 1
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1406 now = currentTimeMillis()
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1407 nexttime = now
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1408 i = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1409 while i < 3:
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1410 if now < nexttime:
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1411 self.wait(nexttime - now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1412 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1413 continue
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1414 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1415 out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1416 _CLASS_IN, ttl, info.name), 0)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1417 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1418 DNSService(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1419 info.name, _TYPE_SRV,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1420 _CLASS_IN, ttl, info.priority, info.weight, info.port,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1421 info.server),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1422 0)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1423 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1424 DNSText(info.name, _TYPE_TXT, _CLASS_IN, ttl, info.text),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1425 0)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1426 if info.address:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1427 out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1428 _CLASS_IN, ttl, info.address), 0)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1429 self.send(out)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1430 i += 1
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1431 nexttime += _REGISTER_TIME
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1432
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1433 def unregisterService(self, info):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1434 """Unregister a service."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1435 try:
28301
fd8a4d2d6541 zeroconf: del is not a function
timeless <timeless@mozdev.org>
parents: 28300
diff changeset
1436 del self.services[info.name.lower()]
28300
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1437 if self.servicetypes[info.type] > 1:
15c5f50e7e13 zeroconf: add whitespace around operator
timeless <timeless@mozdev.org>
parents: 28299
diff changeset
1438 self.servicetypes[info.type] -= 1
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1439 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1440 del self.servicetypes[info.type]
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1441 except KeyError:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1442 pass
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1443 now = currentTimeMillis()
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1444 nexttime = now
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1445 i = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1446 while i < 3:
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1447 if now < nexttime:
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1448 self.wait(nexttime - now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1449 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1450 continue
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1451 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1452 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1453 DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1454 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1455 DNSService(info.name, _TYPE_SRV,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1456 _CLASS_IN, 0, info.priority, info.weight, info.port,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1457 info.name),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1458 0)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1459 out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1460 _CLASS_IN, 0, info.text), 0)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1461 if info.address:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1462 out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1463 _CLASS_IN, 0, info.address), 0)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1464 self.send(out)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1465 i += 1
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1466 nexttime += _UNREGISTER_TIME
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1467
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1468 def unregisterAllServices(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1469 """Unregister all registered services."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1470 if len(self.services) > 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1471 now = currentTimeMillis()
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1472 nexttime = now
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1473 i = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1474 while i < 3:
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1475 if now < nexttime:
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1476 self.wait(nexttime - now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1477 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1478 continue
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1479 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1480 for info in self.services.values():
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1481 out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1482 _CLASS_IN, 0, info.name), 0)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1483 out.addAnswerAtTime(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1484 DNSService(info.name, _TYPE_SRV,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1485 _CLASS_IN, 0, info.priority, info.weight,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1486 info.port, info.server),
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1487 0)
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1488 out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1489 _CLASS_IN, 0, info.text), 0)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1490 if info.address:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1491 out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1492 _CLASS_IN, 0, info.address), 0)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1493 self.send(out)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1494 i += 1
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1495 nexttime += _UNREGISTER_TIME
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1496
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1497 def checkService(self, info):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1498 """Checks the network for a unique service name, modifying the
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1499 ServiceInfo passed in if it is not unique."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1500 now = currentTimeMillis()
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1501 nexttime = now
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1502 i = 0
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1503 while i < 3:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1504 for record in self.cache.entriesWithName(info.type):
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1505 if (record.type == _TYPE_PTR and not record.isExpired(now) and
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1506 record.alias == info.name):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1507 if (info.name.find('.') < 0):
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1508 info.name = ("%w.[%s:%d].%s" %
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1509 (info.name, info.address, info.port, info.type))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1510 self.checkService(info)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1511 return
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1512 raise NonUniqueNameException
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1513 if now < nexttime:
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1514 self.wait(nexttime - now)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1515 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1516 continue
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1517 out = DNSOutgoing(_FLAGS_QR_QUERY | _FLAGS_AA)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1518 self.debug = out
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1519 out.addQuestion(DNSQuestion(info.type, _TYPE_PTR, _CLASS_IN))
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1520 out.addAuthoritativeAnswer(DNSPointer(info.type, _TYPE_PTR,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1521 _CLASS_IN, _DNS_TTL, info.name))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1522 self.send(out)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1523 i += 1
28419
eb9d0e828c30 zeroconf: remove camelcase in identifiers
timeless <timeless@mozdev.org>
parents: 28302
diff changeset
1524 nexttime += _CHECK_TIME
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1525
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1526 def addListener(self, listener, question):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1527 """Adds a listener for a given question. The listener will have
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1528 its updateRecord method called when information is available to
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1529 answer the question."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1530 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1531 self.listeners.append(listener)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1532 if question is not None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1533 for record in self.cache.entriesWithName(question.name):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1534 if question.answeredBy(record) and not record.isExpired(now):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1535 listener.updateRecord(self, now, record)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1536 self.notifyAll()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1537
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1538 def removeListener(self, listener):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1539 """Removes a listener."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1540 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1541 self.listeners.remove(listener)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1542 self.notifyAll()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1543 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1544 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1545
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1546 def updateRecord(self, now, rec):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1547 """Used to notify listeners of new information that has updated
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1548 a record."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1549 for listener in self.listeners:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1550 listener.updateRecord(self, now, rec)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1551 self.notifyAll()
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1552
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1553 def handleResponse(self, msg):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1554 """Deal with incoming response packets. All answers
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1555 are held in the cache, and listeners are notified."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1556 now = currentTimeMillis()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1557 for record in msg.answers:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1558 expired = record.isExpired(now)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1559 if record in self.cache.entries():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1560 if expired:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1561 self.cache.remove(record)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1562 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1563 entry = self.cache.get(record)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1564 if entry is not None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1565 entry.resetTTL(record)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1566 record = entry
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1567 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1568 self.cache.add(record)
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1569
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1570 self.updateRecord(now, record)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1571
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1572 def handleQuery(self, msg, addr, port):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1573 """Deal with incoming query packets. Provides a response if
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1574 possible."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1575 out = None
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1576
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1577 # Support unicast client responses
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1578 #
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1579 if port != _MDNS_PORT:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1580 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA, 0)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1581 for question in msg.questions:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1582 out.addQuestion(question)
7874
d812029cda85 cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7071
diff changeset
1583
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1584 for question in msg.questions:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1585 if question.type == _TYPE_PTR:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1586 if question.name == "_services._dns-sd._udp.local.":
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1587 for stype in self.servicetypes.keys():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1588 if out is None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1589 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1590 out.addAnswer(msg,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1591 DNSPointer(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1592 "_services._dns-sd._udp.local.",
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1593 _TYPE_PTR, _CLASS_IN,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1594 _DNS_TTL, stype))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1595 for service in self.services.values():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1596 if question.name == service.type:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1597 if out is None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1598 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1599 out.addAnswer(msg, DNSPointer(service.type, _TYPE_PTR,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1600 _CLASS_IN, _DNS_TTL, service.name))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1601 else:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1602 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1603 if out is None:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1604 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
7874
d812029cda85 cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7071
diff changeset
1605
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1606 # Answer A record queries for any service addresses we know
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1607 if question.type == _TYPE_A or question.type == _TYPE_ANY:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1608 for service in self.services.values():
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1609 if service.server == question.name.lower():
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1610 out.addAnswer(msg,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1611 DNSAddress(question.name, _TYPE_A,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1612 _CLASS_IN | _CLASS_UNIQUE,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1613 _DNS_TTL, service.address))
7874
d812029cda85 cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7071
diff changeset
1614
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1615 service = self.services.get(question.name.lower(), None)
35629
31451f3f4b56 style: remove multiple statement on a single line in zeroconf
Boris Feld <boris.feld@octobus.net>
parents: 34447
diff changeset
1616 if not service:
31451f3f4b56 style: remove multiple statement on a single line in zeroconf
Boris Feld <boris.feld@octobus.net>
parents: 34447
diff changeset
1617 continue
7874
d812029cda85 cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7071
diff changeset
1618
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1619 if (question.type == _TYPE_SRV or
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1620 question.type == _TYPE_ANY):
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1621 out.addAnswer(msg,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1622 DNSService(question.name, _TYPE_SRV,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1623 _CLASS_IN | _CLASS_UNIQUE,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1624 _DNS_TTL, service.priority,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1625 service.weight, service.port,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1626 service.server))
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1627 if (question.type == _TYPE_TXT or
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1628 question.type == _TYPE_ANY):
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1629 out.addAnswer(msg, DNSText(question.name, _TYPE_TXT,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1630 _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.text))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1631 if question.type == _TYPE_SRV:
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1632 out.addAdditionalAnswer(
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1633 DNSAddress(service.server, _TYPE_A,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1634 _CLASS_IN | _CLASS_UNIQUE,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1635 _DNS_TTL, service.address))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1636 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1637 traceback.print_exc()
7874
d812029cda85 cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7071
diff changeset
1638
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1639 if out is not None and out.answers:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1640 out.id = msg.id
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1641 self.send(out, addr, port)
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1642
28302
e96a3ae025ed zeroconf: remove whitespace around = for named parameters
timeless <timeless@mozdev.org>
parents: 28301
diff changeset
1643 def send(self, out, addr=_MDNS_ADDR, port=_MDNS_PORT):
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1644 """Sends an outgoing packet."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1645 # This is a quick test to see if we can parse the packets we generate
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1646 #temp = DNSIncoming(out.packet())
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1647 try:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1648 self.socket.sendto(out.packet(), 0, (addr, port))
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1649 except Exception:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1650 # Ignore this, it may be a temporary loss of network connection
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1651 pass
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1652
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1653 def close(self):
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1654 """Ends the background threads, and prevent this instance from
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1655 servicing further queries."""
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1656 if globals()['_GLOBAL_DONE'] == 0:
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1657 globals()['_GLOBAL_DONE'] = 1
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1658 self.notifyAll()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1659 self.engine.notify()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1660 self.unregisterAllServices()
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1661 self.socket.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP,
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1662 socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1663 self.socket.close()
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1664
7071
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1665 # Test a few module features, including service registration, service
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1666 # query (for Zoe), and service unregistration.
643c751e60b2 zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1667
7877
eba7f12b0c51 cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7874
diff changeset
1668 if __name__ == '__main__':
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1669 print("Multicast DNS Service Discovery for Python, version", __version__)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1670 r = Zeroconf()
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1671 print("1. Testing registration of a service...")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1672 desc = {'version':'0.10','a':'test value', 'b':'another value'}
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1673 info = ServiceInfo("_http._tcp.local.",
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1674 "My Service Name._http._tcp.local.",
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1675 socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc)
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1676 print(" Registering service...")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1677 r.registerService(info)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1678 print(" Registration done.")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1679 print("2. Testing query of service information...")
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1680 print(" Getting ZOE service:",
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1681 str(r.getServiceInfo("_http._tcp.local.", "ZOE._http._tcp.local.")))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1682 print(" Query done.")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1683 print("3. Testing query of own service...")
28299
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1684 print(" Getting self:",
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1685 str(r.getServiceInfo("_http._tcp.local.",
acea9dd8cf7e zeroconf: wrap long lines
timeless <timeless@mozdev.org>
parents: 28298
diff changeset
1686 "My Service Name._http._tcp.local.")))
28298
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1687 print(" Query done.")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1688 print("4. Testing unregister of service information...")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1689 r.unregisterService(info)
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1690 print(" Unregister done.")
c318e8fd0e62 zeroconf: drop tabs
timeless <timeless@mozdev.org>
parents: 28297
diff changeset
1691 r.close()