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