annotate hgext/zeroconf/Zeroconf.py @ 30604:b654112a0119

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