Mercurial > hg
annotate hgext/zeroconf/Zeroconf.py @ 9021:2ccb527c7b1a
gendoc: fix localization of help topic
When a topic provides a callable method for its text, most likely
this text will be generated from different parts, so it does not
make sense to apply gettext on the whole result, rather the method
should provide translation by itself.
This is the case with the extensions topic, which triggers a double
gettext call, making the ASCII codec fail when it encounters 8 bit
characters, and prevents the documentation from being built.
author | Cédric Duval <cedricduval@free.fr> |
---|---|
date | Sat, 04 Jul 2009 12:12:36 +0200 |
parents | b0d945b95105 |
children | e0121ad90b57 |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
20 License along with this library; if not, write to the Free Software |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
69 """0.05 update - ensure case insensitivty on domain names |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
117 _FLAGS_AA = 0x0400 # Authorative answer |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
207 # implementation classes |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
208 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
209 class DNSEntry(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
210 """A DNS entry""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
211 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
212 def __init__(self, name, type, clazz): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
213 self.key = string.lower(name) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
214 self.name = name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
215 self.type = type |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
216 self.clazz = clazz & _CLASS_MASK |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
217 self.unique = (clazz & _CLASS_UNIQUE) != 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
218 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
219 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
220 """Equality test on name, type, and class""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
221 if isinstance(other, DNSEntry): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
222 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
|
223 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
224 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
225 def __ne__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
226 """Non-equality test""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
227 return not self.__eq__(other) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
228 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
229 def getClazz(self, clazz): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
230 """Class accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
231 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
232 return _CLASSES[clazz] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
233 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
234 return "?(%s)" % (clazz) |
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 getType(self, type): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
237 """Type 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 _TYPES[type] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
240 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
241 return "?(%s)" % (type) |
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 toString(self, hdr, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
244 """String representation with additional information""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
245 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
|
246 if self.unique: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
247 result += "-unique," |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
248 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
249 result += "," |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
250 result += self.name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
251 if other is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
252 result += ",%s]" % (other) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
253 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
254 result += "]" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
255 return result |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
256 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
257 class DNSQuestion(DNSEntry): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
258 """A DNS question entry""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
259 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
260 def __init__(self, name, type, clazz): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
261 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
|
262 raise NonLocalNameException(name) |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
263 DNSEntry.__init__(self, name, type, clazz) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
264 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
265 def answeredBy(self, rec): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
266 """Returns true if the question is answered by the record""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
267 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
|
268 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
269 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
270 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
271 return DNSEntry.toString(self, "question", None) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
272 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
273 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
274 class DNSRecord(DNSEntry): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
275 """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
|
276 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
277 def __init__(self, name, type, clazz, ttl): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
278 DNSEntry.__init__(self, name, type, clazz) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
279 self.ttl = ttl |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
280 self.created = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
281 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
282 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
283 """Tests equality as per DNSRecord""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
284 if isinstance(other, DNSRecord): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
285 return DNSEntry.__eq__(self, other) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
286 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
287 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
288 def suppressedBy(self, msg): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
289 """Returns true if any answer in a message can suffice for the |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
290 information held in this record.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
291 for record in msg.answers: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
292 if self.suppressedByAnswer(record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
293 return 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
294 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
295 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
296 def suppressedByAnswer(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
297 """Returns true if another record has same name, type and class, |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
298 and if its TTL is at least half of this record's.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
299 if self == other and other.ttl > (self.ttl / 2): |
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 getExpirationTime(self, percent): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
304 """Returns the time at which this record will have expired |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
305 by a certain percentage.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
306 return self.created + (percent * self.ttl * 10) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
307 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
308 def getRemainingTTL(self, now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
309 """Returns the remaining TTL in seconds.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
310 return max(0, (self.getExpirationTime(100) - now) / 1000) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
311 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
312 def isExpired(self, now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
313 """Returns true if this record has expired.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
314 return self.getExpirationTime(100) <= now |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
315 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
316 def isStale(self, now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
317 """Returns true if this record is at least half way expired.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
318 return self.getExpirationTime(50) <= now |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
319 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
320 def resetTTL(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
321 """Sets this record's TTL and created time to that of |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
322 another record.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
323 self.created = other.created |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
324 self.ttl = other.ttl |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
325 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
326 def write(self, out): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
327 """Abstract method""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
328 raise AbstractMethodException |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
329 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
330 def toString(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
331 """String representation with addtional information""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
332 arg = "%s/%s,%s" % (self.ttl, self.getRemainingTTL(currentTimeMillis()), other) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
333 return DNSEntry.toString(self, "record", arg) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
334 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
335 class DNSAddress(DNSRecord): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
336 """A DNS address record""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
337 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
338 def __init__(self, name, type, clazz, ttl, address): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
339 DNSRecord.__init__(self, name, type, clazz, ttl) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
340 self.address = address |
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 def write(self, out): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
343 """Used in constructing an outgoing packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
344 out.writeString(self.address, len(self.address)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
345 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
346 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
347 """Tests equality on address""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
348 if isinstance(other, DNSAddress): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
349 return self.address == other.address |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
350 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
351 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
352 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
353 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
354 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
355 return socket.inet_ntoa(self.address) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
356 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
357 return self.address |
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 class DNSHinfo(DNSRecord): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
360 """A DNS host information record""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
361 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
362 def __init__(self, name, type, clazz, ttl, cpu, os): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
363 DNSRecord.__init__(self, name, type, clazz, ttl) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
364 self.cpu = cpu |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
365 self.os = os |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
366 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
367 def write(self, out): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
368 """Used in constructing an outgoing packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
369 out.writeString(self.cpu, len(self.cpu)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
370 out.writeString(self.os, len(self.os)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
371 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
372 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
373 """Tests equality on cpu and os""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
374 if isinstance(other, DNSHinfo): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
375 return self.cpu == other.cpu and self.os == other.os |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
376 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
377 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
378 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
379 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
380 return self.cpu + " " + self.os |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
381 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
382 class DNSPointer(DNSRecord): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
383 """A DNS pointer record""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
384 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
385 def __init__(self, name, type, clazz, ttl, alias): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
386 DNSRecord.__init__(self, name, type, clazz, ttl) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
387 self.alias = alias |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
388 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
389 def write(self, out): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
390 """Used in constructing an outgoing packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
391 out.writeName(self.alias) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
392 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
393 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
394 """Tests equality on alias""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
395 if isinstance(other, DNSPointer): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
396 return self.alias == other.alias |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
397 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
398 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
399 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
400 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
401 return self.toString(self.alias) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
402 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
403 class DNSText(DNSRecord): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
404 """A DNS text record""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
405 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
406 def __init__(self, name, type, clazz, ttl, text): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
407 DNSRecord.__init__(self, name, type, clazz, ttl) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
408 self.text = text |
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 def write(self, out): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
411 """Used in constructing an outgoing packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
412 out.writeString(self.text, len(self.text)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
413 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
414 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
415 """Tests equality on text""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
416 if isinstance(other, DNSText): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
417 return self.text == other.text |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
418 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
419 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
420 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
421 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
422 if len(self.text) > 10: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
423 return self.toString(self.text[:7] + "...") |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
424 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
425 return self.toString(self.text) |
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 class DNSService(DNSRecord): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
428 """A DNS service record""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
429 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
430 def __init__(self, name, type, clazz, ttl, priority, weight, port, server): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
431 DNSRecord.__init__(self, name, type, clazz, ttl) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
432 self.priority = priority |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
433 self.weight = weight |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
434 self.port = port |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
435 self.server = server |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
436 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
437 def write(self, out): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
438 """Used in constructing an outgoing packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
439 out.writeShort(self.priority) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
440 out.writeShort(self.weight) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
441 out.writeShort(self.port) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
442 out.writeName(self.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 __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
445 """Tests equality on priority, weight, port and server""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
446 if isinstance(other, DNSService): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
447 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
|
448 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
449 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
450 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
451 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
452 return self.toString("%s:%s" % (self.server, self.port)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
453 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
454 class DNSIncoming(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
455 """Object representation of an incoming DNS packet""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
456 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
457 def __init__(self, data): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
458 """Constructor from string holding bytes of packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
459 self.offset = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
460 self.data = data |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
461 self.questions = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
462 self.answers = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
463 self.numQuestions = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
464 self.numAnswers = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
465 self.numAuthorities = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
466 self.numAdditionals = 0 |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
467 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
468 self.readHeader() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
469 self.readQuestions() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
470 self.readOthers() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
471 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
472 def readHeader(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
473 """Reads header portion of packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
474 format = '!HHHHHH' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
475 length = struct.calcsize(format) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
476 info = struct.unpack(format, self.data[self.offset:self.offset+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
477 self.offset += length |
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 self.id = info[0] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
480 self.flags = info[1] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
481 self.numQuestions = info[2] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
482 self.numAnswers = info[3] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
483 self.numAuthorities = info[4] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
484 self.numAdditionals = info[5] |
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 def readQuestions(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
487 """Reads questions section of packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
488 format = '!HH' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
489 length = struct.calcsize(format) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
490 for i in range(0, self.numQuestions): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
491 name = self.readName() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
492 info = struct.unpack(format, self.data[self.offset:self.offset+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
493 self.offset += length |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
494 |
8131
b0d945b95105
zeroconf: don't fail on non-local names
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7877
diff
changeset
|
495 try: |
b0d945b95105
zeroconf: don't fail on non-local names
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7877
diff
changeset
|
496 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
|
497 self.questions.append(question) |
b0d945b95105
zeroconf: don't fail on non-local names
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7877
diff
changeset
|
498 except NonLocalNameException: |
b0d945b95105
zeroconf: don't fail on non-local names
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7877
diff
changeset
|
499 pass |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
500 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
501 def readInt(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
502 """Reads an integer from the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
503 format = '!I' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
504 length = struct.calcsize(format) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
505 info = struct.unpack(format, self.data[self.offset:self.offset+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
506 self.offset += length |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
507 return info[0] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
508 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
509 def readCharacterString(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
510 """Reads a character string from the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
511 length = ord(self.data[self.offset]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
512 self.offset += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
513 return self.readString(length) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
514 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
515 def readString(self, len): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
516 """Reads a string of a given length from the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
517 format = '!' + str(len) + 's' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
518 length = struct.calcsize(format) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
519 info = struct.unpack(format, self.data[self.offset:self.offset+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
520 self.offset += length |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
521 return info[0] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
522 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
523 def readUnsignedShort(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
524 """Reads an unsigned short from the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
525 format = '!H' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
526 length = struct.calcsize(format) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
527 info = struct.unpack(format, self.data[self.offset:self.offset+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
528 self.offset += length |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
529 return info[0] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
530 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
531 def readOthers(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
532 """Reads the answers, authorities and additionals section of the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
533 format = '!HHiH' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
534 length = struct.calcsize(format) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
535 n = self.numAnswers + self.numAuthorities + self.numAdditionals |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
536 for i in range(0, n): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
537 domain = self.readName() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
538 info = struct.unpack(format, self.data[self.offset:self.offset+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
539 self.offset += length |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
540 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
541 rec = None |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
542 if info[0] == _TYPE_A: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
543 rec = DNSAddress(domain, info[0], info[1], info[2], self.readString(4)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
544 elif info[0] == _TYPE_CNAME or info[0] == _TYPE_PTR: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
545 rec = DNSPointer(domain, info[0], info[1], info[2], self.readName()) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
546 elif info[0] == _TYPE_TXT: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
547 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
|
548 elif info[0] == _TYPE_SRV: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
549 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
|
550 elif info[0] == _TYPE_HINFO: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
551 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
|
552 elif info[0] == _TYPE_AAAA: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
553 rec = DNSAddress(domain, info[0], info[1], info[2], self.readString(16)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
554 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
555 # Try to ignore types we don't know about |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
556 # this may mean the rest of the name is |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
557 # unable to be parsed, and may show errors |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
558 # so this is left for debugging. New types |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
559 # encountered need to be parsed properly. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
560 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
561 #print "UNKNOWN TYPE = " + str(info[0]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
562 #raise BadTypeInNameException |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
563 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
564 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
565 if rec is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
566 self.answers.append(rec) |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
567 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
568 def isQuery(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
569 """Returns true if this is a query""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
570 return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_QUERY |
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 def isResponse(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
573 """Returns true if this is a response""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
574 return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_RESPONSE |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
575 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
576 def readUTF(self, offset, len): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
577 """Reads a UTF-8 string of a given length from the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
578 result = self.data[offset:offset+len].decode('utf-8') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
579 return result |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
580 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
581 def readName(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
582 """Reads a domain name from the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
583 result = '' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
584 off = self.offset |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
585 next = -1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
586 first = off |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
587 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
588 while 1: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
589 len = ord(self.data[off]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
590 off += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
591 if len == 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
592 break |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
593 t = len & 0xC0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
594 if t == 0x00: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
595 result = ''.join((result, self.readUTF(off, len) + '.')) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
596 off += len |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
597 elif t == 0xC0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
598 if next < 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
599 next = off + 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
600 off = ((len & 0x3F) << 8) | ord(self.data[off]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
601 if off >= first: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
602 raise "Bad domain name (circular) at " + str(off) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
603 first = off |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
604 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
605 raise "Bad domain name at " + str(off) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
606 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
607 if next >= 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
608 self.offset = next |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
609 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
610 self.offset = off |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
611 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
612 return result |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
613 |
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
614 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
615 class DNSOutgoing(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
616 """Object representation of an outgoing packet""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
617 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
618 def __init__(self, flags, multicast = 1): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
619 self.finished = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
620 self.id = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
621 self.multicast = multicast |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
622 self.flags = flags |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
623 self.names = {} |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
624 self.data = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
625 self.size = 12 |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
626 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
627 self.questions = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
628 self.answers = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
629 self.authorities = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
630 self.additionals = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
631 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
632 def addQuestion(self, record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
633 """Adds a question""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
634 self.questions.append(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
635 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
636 def addAnswer(self, inp, record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
637 """Adds an answer""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
638 if not record.suppressedBy(inp): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
639 self.addAnswerAtTime(record, 0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
640 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
641 def addAnswerAtTime(self, record, now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
642 """Adds an answer if if does not expire by a certain time""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
643 if record is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
644 if now == 0 or not record.isExpired(now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
645 self.answers.append((record, now)) |
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 addAuthorativeAnswer(self, record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
648 """Adds an authoritative answer""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
649 self.authorities.append(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
650 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
651 def addAdditionalAnswer(self, record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
652 """Adds an additional answer""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
653 self.additionals.append(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
654 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
655 def writeByte(self, value): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
656 """Writes a single byte to the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
657 format = '!c' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
658 self.data.append(struct.pack(format, chr(value))) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
659 self.size += 1 |
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 insertShort(self, index, value): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
662 """Inserts an unsigned short in a certain position in the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
663 format = '!H' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
664 self.data.insert(index, struct.pack(format, value)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
665 self.size += 2 |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
666 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
667 def writeShort(self, value): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
668 """Writes an unsigned short to 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.append(struct.pack(format, value)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
671 self.size += 2 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
672 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
673 def writeInt(self, value): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
674 """Writes an unsigned integer to the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
675 format = '!I' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
676 self.data.append(struct.pack(format, int(value))) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
677 self.size += 4 |
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 writeString(self, value, length): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
680 """Writes a string to the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
681 format = '!' + str(length) + 's' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
682 self.data.append(struct.pack(format, value)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
683 self.size += length |
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 writeUTF(self, s): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
686 """Writes a UTF-8 string of a given length to the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
687 utfstr = s.encode('utf-8') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
688 length = len(utfstr) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
689 if length > 64: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
690 raise NamePartTooLongException |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
691 self.writeByte(length) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
692 self.writeString(utfstr, length) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
693 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
694 def writeName(self, name): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
695 """Writes a domain name to the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
696 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
697 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
698 # Find existing instance of this name in packet |
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 index = self.names[name] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
701 except KeyError: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
702 # No record of this name already, so write it |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
703 # out as normal, recording the location of the name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
704 # for future pointers to it. |
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 self.names[name] = self.size |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
707 parts = name.split('.') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
708 if parts[-1] == '': |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
709 parts = parts[:-1] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
710 for part in parts: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
711 self.writeUTF(part) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
712 self.writeByte(0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
713 return |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
714 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
715 # An index was found, so write a pointer to it |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
716 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
717 self.writeByte((index >> 8) | 0xC0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
718 self.writeByte(index) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
719 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
720 def writeQuestion(self, question): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
721 """Writes a question to the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
722 self.writeName(question.name) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
723 self.writeShort(question.type) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
724 self.writeShort(question.clazz) |
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 writeRecord(self, record, now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
727 """Writes a record (answer, authoritative answer, additional) to |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
728 the packet""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
729 self.writeName(record.name) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
730 self.writeShort(record.type) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
731 if record.unique and self.multicast: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
732 self.writeShort(record.clazz | _CLASS_UNIQUE) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
733 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
734 self.writeShort(record.clazz) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
735 if now == 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
736 self.writeInt(record.ttl) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
737 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
738 self.writeInt(record.getRemainingTTL(now)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
739 index = len(self.data) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
740 # Adjust size for the short we will write before this record |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
741 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
742 self.size += 2 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
743 record.write(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
744 self.size -= 2 |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
745 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
746 length = len(''.join(self.data[index:])) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
747 self.insertShort(index, length) # Here is the short we adjusted for |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
748 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
749 def packet(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
750 """Returns a string containing the packet's bytes |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
751 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
752 No further parts should be added to the packet once this |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
753 is done.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
754 if not self.finished: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
755 self.finished = 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
756 for question in self.questions: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
757 self.writeQuestion(question) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
758 for answer, time in self.answers: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
759 self.writeRecord(answer, time) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
760 for authority in self.authorities: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
761 self.writeRecord(authority, 0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
762 for additional in self.additionals: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
763 self.writeRecord(additional, 0) |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
764 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
765 self.insertShort(0, len(self.additionals)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
766 self.insertShort(0, len(self.authorities)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
767 self.insertShort(0, len(self.answers)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
768 self.insertShort(0, len(self.questions)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
769 self.insertShort(0, self.flags) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
770 if self.multicast: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
771 self.insertShort(0, 0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
772 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
773 self.insertShort(0, self.id) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
774 return ''.join(self.data) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
775 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
776 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
777 class DNSCache(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
778 """A cache of DNS entries""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
779 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
780 def __init__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
781 self.cache = {} |
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 def add(self, entry): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
784 """Adds an entry""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
785 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
786 list = self.cache[entry.key] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
787 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
788 list = self.cache[entry.key] = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
789 list.append(entry) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
790 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
791 def remove(self, entry): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
792 """Removes an entry""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
793 try: |
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.remove(entry) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
796 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
797 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
798 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
799 def get(self, entry): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
800 """Gets an entry by key. Will return None if there is no |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
801 matching entry.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
802 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
803 list = self.cache[entry.key] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
804 return list[list.index(entry)] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
805 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
806 return None |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
807 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
808 def getByDetails(self, name, type, clazz): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
809 """Gets an entry by details. Will return None if there is |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
810 no matching entry.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
811 entry = DNSEntry(name, type, clazz) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
812 return self.get(entry) |
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 entriesWithName(self, name): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
815 """Returns a list of entries whose key matches the name.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
816 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
817 return self.cache[name] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
818 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
819 return [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
820 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
821 def entries(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
822 """Returns a list of all entries""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
823 def add(x, y): return x+y |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
824 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
825 return reduce(add, self.cache.values()) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
826 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
827 return [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
828 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
829 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
830 class Engine(threading.Thread): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
831 """An engine wraps read access to sockets, allowing objects that |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
832 need to receive data from sockets to be called back when the |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
833 sockets are ready. |
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 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
|
836 it is interested in is ready for reading. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
837 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
838 Writers are not implemented here, because we only send short |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
839 packets. |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
842 def __init__(self, zeroconf): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
843 threading.Thread.__init__(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
844 self.zeroconf = zeroconf |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
845 self.readers = {} # maps socket to reader |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
846 self.timeout = 5 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
847 self.condition = threading.Condition() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
848 self.start() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
849 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
850 def run(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
851 while not globals()['_GLOBAL_DONE']: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
852 rs = self.getReaders() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
853 if len(rs) == 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
854 # No sockets to manage, but we wait for the timeout |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
855 # or addition of a socket |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
856 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
857 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
858 self.condition.wait(self.timeout) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
859 self.condition.release() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
860 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
861 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
862 rr, wr, er = select.select(rs, [], [], self.timeout) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
863 for socket in rr: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
864 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
865 self.readers[socket].handle_read() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
866 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
867 traceback.print_exc() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
868 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
869 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
870 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
871 def getReaders(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
872 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
873 result = self.readers.keys() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
874 self.condition.release() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
875 return result |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
876 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
877 def addReader(self, reader, socket): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
878 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
879 self.readers[socket] = reader |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
880 self.condition.notify() |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
883 def delReader(self, socket): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
884 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
885 del(self.readers[socket]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
886 self.condition.notify() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
887 self.condition.release() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
888 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
889 def notify(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
890 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
891 self.condition.notify() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
892 self.condition.release() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
893 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
894 class Listener(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
895 """A Listener is used by this module to listen on the multicast |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
896 group to which DNS messages are sent, allowing the implementation |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
897 to cache information as it arrives. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
898 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
899 It requires registration with an Engine object in order to have |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
900 the read() method called when a socket is availble for reading.""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
901 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
902 def __init__(self, zeroconf): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
903 self.zeroconf = zeroconf |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
904 self.zeroconf.engine.addReader(self, self.zeroconf.socket) |
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 def handle_read(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
907 data, (addr, port) = self.zeroconf.socket.recvfrom(_MAX_MSG_ABSOLUTE) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
908 self.data = data |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
909 msg = DNSIncoming(data) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
910 if msg.isQuery(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
911 # Always multicast responses |
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 if port == _MDNS_PORT: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
914 self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
915 # If it's not a multicast query, reply via unicast |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
916 # and multicast |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
917 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
918 elif port == _DNS_PORT: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
919 self.zeroconf.handleQuery(msg, addr, port) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
920 self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
921 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
922 self.zeroconf.handleResponse(msg) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
923 |
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 class Reaper(threading.Thread): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
926 """A Reaper is used by this module to remove cache entries that |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
927 have expired.""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
928 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
929 def __init__(self, zeroconf): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
930 threading.Thread.__init__(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
931 self.zeroconf = zeroconf |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
932 self.start() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
933 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
934 def run(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
935 while 1: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
936 self.zeroconf.wait(10 * 1000) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
937 if globals()['_GLOBAL_DONE']: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
938 return |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
939 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
940 for record in self.zeroconf.cache.entries(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
941 if record.isExpired(now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
942 self.zeroconf.updateRecord(now, record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
943 self.zeroconf.cache.remove(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
944 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
945 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
946 class ServiceBrowser(threading.Thread): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
947 """Used to browse for a service of a specific type. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
948 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
949 The listener object will have its addService() and |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
950 removeService() methods called when this browser |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
951 discovers changes in the services availability.""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
952 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
953 def __init__(self, zeroconf, type, listener): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
954 """Creates a browser for a specific type""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
955 threading.Thread.__init__(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
956 self.zeroconf = zeroconf |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
957 self.type = type |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
958 self.listener = listener |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
959 self.services = {} |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
960 self.nextTime = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
961 self.delay = _BROWSER_TIME |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
962 self.list = [] |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
963 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
964 self.done = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
965 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
966 self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
967 self.start() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
968 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
969 def updateRecord(self, zeroconf, now, record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
970 """Callback invoked by Zeroconf when new information arrives. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
971 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
972 Updates information required by browser in the Zeroconf cache.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
973 if record.type == _TYPE_PTR and record.name == self.type: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
974 expired = record.isExpired(now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
975 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
976 oldrecord = self.services[record.alias.lower()] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
977 if not expired: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
978 oldrecord.resetTTL(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
979 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
980 del(self.services[record.alias.lower()]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
981 callback = lambda x: self.listener.removeService(x, self.type, record.alias) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
982 self.list.append(callback) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
983 return |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
984 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
985 if not expired: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
986 self.services[record.alias.lower()] = record |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
987 callback = lambda x: self.listener.addService(x, self.type, record.alias) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
988 self.list.append(callback) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
989 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
990 expires = record.getExpirationTime(75) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
991 if expires < self.nextTime: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
992 self.nextTime = expires |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
993 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
994 def cancel(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
995 self.done = 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
996 self.zeroconf.notifyAll() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
997 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
998 def run(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
999 while 1: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1000 event = None |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1001 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1002 if len(self.list) == 0 and self.nextTime > now: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1003 self.zeroconf.wait(self.nextTime - now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1004 if globals()['_GLOBAL_DONE'] or self.done: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1005 return |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1006 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1007 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1008 if self.nextTime <= now: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1009 out = DNSOutgoing(_FLAGS_QR_QUERY) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1010 out.addQuestion(DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1011 for record in self.services.values(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1012 if not record.isExpired(now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1013 out.addAnswerAtTime(record, now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1014 self.zeroconf.send(out) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1015 self.nextTime = now + self.delay |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1016 self.delay = min(20 * 1000, self.delay * 2) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1017 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1018 if len(self.list) > 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1019 event = self.list.pop(0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1020 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1021 if event is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1022 event(self.zeroconf) |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1023 |
7071
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 class ServiceInfo(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1026 """Service information""" |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1027 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1028 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
|
1029 """Create a service description. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1030 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1031 type: fully qualified service type name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1032 name: fully qualified service name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1033 address: IP address as unsigned short, network byte order |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1034 port: port that the service runs on |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1035 weight: weight of the service |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1036 priority: priority of the service |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1037 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
|
1038 server: fully qualified name for service host (defaults to name)""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1039 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1040 if not name.endswith(type): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1041 raise BadTypeInNameException |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1042 self.type = type |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1043 self.name = name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1044 self.address = address |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1045 self.port = port |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1046 self.weight = weight |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1047 self.priority = priority |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1048 if server: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1049 self.server = server |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1050 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1051 self.server = name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1052 self.setProperties(properties) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1053 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1054 def setProperties(self, properties): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1055 """Sets properties and text of this info from a dictionary""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1056 if isinstance(properties, dict): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1057 self.properties = properties |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1058 list = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1059 result = '' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1060 for key in properties: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1061 value = properties[key] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1062 if value is None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1063 suffix = ''.encode('utf-8') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1064 elif isinstance(value, str): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1065 suffix = value.encode('utf-8') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1066 elif isinstance(value, int): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1067 if value: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1068 suffix = 'true' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1069 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1070 suffix = 'false' |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1071 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1072 suffix = ''.encode('utf-8') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1073 list.append('='.join((key, suffix))) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1074 for item in list: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1075 result = ''.join((result, struct.pack('!c', chr(len(item))), item)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1076 self.text = result |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1077 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1078 self.text = properties |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1079 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1080 def setText(self, text): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1081 """Sets properties and text given a text field""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1082 self.text = text |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1083 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1084 result = {} |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1085 end = len(text) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1086 index = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1087 strs = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1088 while index < end: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1089 length = ord(text[index]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1090 index += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1091 strs.append(text[index:index+length]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1092 index += length |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1093 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1094 for s in strs: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1095 eindex = s.find('=') |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1096 if eindex == -1: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1097 # No equals sign at all |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1098 key = s |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1099 value = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1100 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1101 key = s[:eindex] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1102 value = s[eindex+1:] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1103 if value == 'true': |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1104 value = 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1105 elif value == 'false' or not value: |
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 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1108 # Only update non-existent properties |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1109 if key and result.get(key) == None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1110 result[key] = value |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1111 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1112 self.properties = result |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1113 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1114 traceback.print_exc() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1115 self.properties = None |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1116 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1117 def getType(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1118 """Type accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1119 return self.type |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1120 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1121 def getName(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1122 """Name accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1123 if self.type is not None and self.name.endswith("." + self.type): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1124 return self.name[:len(self.name) - len(self.type) - 1] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1125 return self.name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1126 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1127 def getAddress(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1128 """Address accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1129 return self.address |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1130 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1131 def getPort(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1132 """Port accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1133 return self.port |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1134 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1135 def getPriority(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1136 """Pirority accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1137 return self.priority |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1138 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1139 def getWeight(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1140 """Weight accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1141 return self.weight |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1142 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1143 def getProperties(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1144 """Properties accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1145 return self.properties |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1146 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1147 def getText(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1148 """Text accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1149 return self.text |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1150 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1151 def getServer(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1152 """Server accessor""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1153 return self.server |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1154 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1155 def updateRecord(self, zeroconf, now, record): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1156 """Updates service information from a DNS record""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1157 if record is not None and not record.isExpired(now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1158 if record.type == _TYPE_A: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1159 #if record.name == self.name: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1160 if record.name == self.server: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1161 self.address = record.address |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1162 elif record.type == _TYPE_SRV: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1163 if record.name == self.name: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1164 self.server = record.server |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1165 self.port = record.port |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1166 self.weight = record.weight |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1167 self.priority = record.priority |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1168 #self.address = None |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1169 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
|
1170 elif record.type == _TYPE_TXT: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1171 if record.name == self.name: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1172 self.setText(record.text) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1173 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1174 def request(self, zeroconf, timeout): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1175 """Returns true if the service could be discovered on the |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1176 network, and updates this object with details discovered. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1177 """ |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1178 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1179 delay = _LISTENER_TIME |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1180 next = now + delay |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1181 last = now + timeout |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1182 result = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1183 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1184 zeroconf.addListener(self, DNSQuestion(self.name, _TYPE_ANY, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1185 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
|
1186 if last <= now: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1187 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1188 if next <= now: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1189 out = DNSOutgoing(_FLAGS_QR_QUERY) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1190 out.addQuestion(DNSQuestion(self.name, _TYPE_SRV, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1191 out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_SRV, _CLASS_IN), now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1192 out.addQuestion(DNSQuestion(self.name, _TYPE_TXT, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1193 out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_TXT, _CLASS_IN), now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1194 if self.server is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1195 out.addQuestion(DNSQuestion(self.server, _TYPE_A, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1196 out.addAnswerAtTime(zeroconf.cache.getByDetails(self.server, _TYPE_A, _CLASS_IN), now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1197 zeroconf.send(out) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1198 next = now + delay |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1199 delay = delay * 2 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1200 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1201 zeroconf.wait(min(next, last) - now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1202 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1203 result = 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1204 finally: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1205 zeroconf.removeListener(self) |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1206 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1207 return result |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1208 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1209 def __eq__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1210 """Tests equality of service name""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1211 if isinstance(other, ServiceInfo): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1212 return other.name == self.name |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1213 return 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1214 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1215 def __ne__(self, other): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1216 """Non-equality test""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1217 return not self.__eq__(other) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1218 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1219 def __repr__(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1220 """String representation""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1221 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
|
1222 if self.text is None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1223 result += "None" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1224 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1225 if len(self.text) < 20: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1226 result += self.text |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1227 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1228 result += self.text[:17] + "..." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1229 result += "]" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1230 return result |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1231 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1232 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1233 class Zeroconf(object): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1234 """Implementation of Zeroconf Multicast DNS Service Discovery |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1235 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1236 Supports registration, unregistration, queries and browsing. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1237 """ |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1238 def __init__(self, bindaddress=None): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1239 """Creates an instance of the Zeroconf class, establishing |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1240 multicast communications, listening and reaping threads.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1241 globals()['_GLOBAL_DONE'] = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1242 if bindaddress is None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1243 self.intf = socket.gethostbyname(socket.gethostname()) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1244 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1245 self.intf = bindaddress |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1246 self.group = ('', _MDNS_PORT) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1247 self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1248 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1249 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1250 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1251 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1252 # SO_REUSEADDR should be equivalent to SO_REUSEPORT for |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1253 # multicast UDP sockets (p 731, "TCP/IP Illustrated, |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1254 # Volume 2"), but some BSD-derived systems require |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1255 # SO_REUSEPORT to be specified explicity. Also, not all |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1256 # versions of Python have SO_REUSEPORT available. So |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1257 # if you're on a BSD-based system, and haven't upgraded |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1258 # to Python 2.3 yet, you may find this library doesn't |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1259 # work as expected. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1260 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1261 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1262 self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 255) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1263 self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1264 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1265 self.socket.bind(self.group) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1266 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1267 # Some versions of linux raise an exception even though |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1268 # the SO_REUSE* options have been set, so ignore it |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1269 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1270 pass |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1271 #self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.intf) + socket.inet_aton('0.0.0.0')) |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1272 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
|
1273 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1274 self.listeners = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1275 self.browsers = [] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1276 self.services = {} |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1277 self.servicetypes = {} |
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.cache = DNSCache() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1280 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1281 self.condition = threading.Condition() |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1282 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1283 self.engine = Engine(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1284 self.listener = Listener(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1285 self.reaper = Reaper(self) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1286 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1287 def isLoopback(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1288 return self.intf.startswith("127.0.0.1") |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1289 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1290 def isLinklocal(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1291 return self.intf.startswith("169.254.") |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1292 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1293 def wait(self, timeout): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1294 """Calling thread waits for a given number of milliseconds or |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1295 until notified.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1296 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1297 self.condition.wait(timeout/1000) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1298 self.condition.release() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1299 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1300 def notifyAll(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1301 """Notifies all waiting threads""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1302 self.condition.acquire() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1303 self.condition.notifyAll() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1304 self.condition.release() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1305 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1306 def getServiceInfo(self, type, name, timeout=3000): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1307 """Returns network's service information for a particular |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1308 name and type, or None if no service matches by the timeout, |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1309 which defaults to 3 seconds.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1310 info = ServiceInfo(type, name) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1311 if info.request(self, timeout): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1312 return info |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1313 return None |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1314 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1315 def addServiceListener(self, type, listener): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1316 """Adds a listener for a particular service type. This object |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1317 will then have its updateRecord method called when information |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1318 arrives for that type.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1319 self.removeServiceListener(listener) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1320 self.browsers.append(ServiceBrowser(self, type, listener)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1321 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1322 def removeServiceListener(self, listener): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1323 """Removes a listener from the set that is currently listening.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1324 for browser in self.browsers: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1325 if browser.listener == listener: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1326 browser.cancel() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1327 del(browser) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1328 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1329 def registerService(self, info, ttl=_DNS_TTL): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1330 """Registers service information to the network with a default TTL |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1331 of 60 seconds. Zeroconf will then respond to requests for |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1332 information for that service. The name of the service may be |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1333 changed if needed to make it unique on the network.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1334 self.checkService(info) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1335 self.services[info.name.lower()] = info |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1336 if self.servicetypes.has_key(info.type): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1337 self.servicetypes[info.type]+=1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1338 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1339 self.servicetypes[info.type]=1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1340 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1341 nextTime = now |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1342 i = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1343 while i < 3: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1344 if now < nextTime: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1345 self.wait(nextTime - now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1346 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1347 continue |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1348 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1349 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
|
1350 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
|
1351 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
|
1352 if info.address: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1353 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
|
1354 self.send(out) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1355 i += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1356 nextTime += _REGISTER_TIME |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1357 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1358 def unregisterService(self, info): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1359 """Unregister a service.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1360 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1361 del(self.services[info.name.lower()]) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1362 if self.servicetypes[info.type]>1: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1363 self.servicetypes[info.type]-=1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1364 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1365 del self.servicetypes[info.type] |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1366 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1367 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1368 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1369 nextTime = now |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1370 i = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1371 while i < 3: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1372 if now < nextTime: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1373 self.wait(nextTime - now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1374 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1375 continue |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1376 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1377 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
|
1378 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
|
1379 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
|
1380 if info.address: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1381 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
|
1382 self.send(out) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1383 i += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1384 nextTime += _UNREGISTER_TIME |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1385 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1386 def unregisterAllServices(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1387 """Unregister all registered services.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1388 if len(self.services) > 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1389 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1390 nextTime = now |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1391 i = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1392 while i < 3: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1393 if now < nextTime: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1394 self.wait(nextTime - now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1395 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1396 continue |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1397 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1398 for info in self.services.values(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1399 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
|
1400 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
|
1401 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
|
1402 if info.address: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1403 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
|
1404 self.send(out) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1405 i += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1406 nextTime += _UNREGISTER_TIME |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1407 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1408 def checkService(self, info): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1409 """Checks the network for a unique service name, modifying the |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1410 ServiceInfo passed in if it is not unique.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1411 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1412 nextTime = now |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1413 i = 0 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1414 while i < 3: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1415 for record in self.cache.entriesWithName(info.type): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1416 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
|
1417 if (info.name.find('.') < 0): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1418 info.name = info.name + ".[" + info.address + ":" + info.port + "]." + info.type |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1419 self.checkService(info) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1420 return |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1421 raise NonUniqueNameException |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1422 if now < nextTime: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1423 self.wait(nextTime - now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1424 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1425 continue |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1426 out = DNSOutgoing(_FLAGS_QR_QUERY | _FLAGS_AA) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1427 self.debug = out |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1428 out.addQuestion(DNSQuestion(info.type, _TYPE_PTR, _CLASS_IN)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1429 out.addAuthorativeAnswer(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, _DNS_TTL, info.name)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1430 self.send(out) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1431 i += 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1432 nextTime += _CHECK_TIME |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1433 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1434 def addListener(self, listener, question): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1435 """Adds a listener for a given question. The listener will have |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1436 its updateRecord method called when information is available to |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1437 answer the question.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1438 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1439 self.listeners.append(listener) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1440 if question is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1441 for record in self.cache.entriesWithName(question.name): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1442 if question.answeredBy(record) and not record.isExpired(now): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1443 listener.updateRecord(self, now, record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1444 self.notifyAll() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1445 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1446 def removeListener(self, listener): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1447 """Removes a listener.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1448 try: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1449 self.listeners.remove(listener) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1450 self.notifyAll() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1451 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1452 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1453 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1454 def updateRecord(self, now, rec): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1455 """Used to notify listeners of new information that has updated |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1456 a record.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1457 for listener in self.listeners: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1458 listener.updateRecord(self, now, rec) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1459 self.notifyAll() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1460 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1461 def handleResponse(self, msg): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1462 """Deal with incoming response packets. All answers |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1463 are held in the cache, and listeners are notified.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1464 now = currentTimeMillis() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1465 for record in msg.answers: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1466 expired = record.isExpired(now) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1467 if record in self.cache.entries(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1468 if expired: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1469 self.cache.remove(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1470 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1471 entry = self.cache.get(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1472 if entry is not None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1473 entry.resetTTL(record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1474 record = entry |
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 self.cache.add(record) |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1477 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1478 self.updateRecord(now, record) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1479 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1480 def handleQuery(self, msg, addr, port): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1481 """Deal with incoming query packets. Provides a response if |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1482 possible.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1483 out = None |
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 # Support unicast client responses |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1486 # |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1487 if port != _MDNS_PORT: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1488 out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA, 0) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1489 for question in msg.questions: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1490 out.addQuestion(question) |
7874
d812029cda85
cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7071
diff
changeset
|
1491 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1492 for question in msg.questions: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1493 if question.type == _TYPE_PTR: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1494 if question.name == "_services._dns-sd._udp.local.": |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1495 for stype in self.servicetypes.keys(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1496 if out is None: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1497 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
|
1498 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
|
1499 for service in self.services.values(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1500 if question.name == service.type: |
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) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1503 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
|
1504 else: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1505 try: |
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) |
7874
d812029cda85
cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7071
diff
changeset
|
1508 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1509 # Answer A record queries for any service addresses we know |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1510 if question.type == _TYPE_A or question.type == _TYPE_ANY: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1511 for service in self.services.values(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1512 if service.server == question.name.lower(): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1513 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
|
1514 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1515 service = self.services.get(question.name.lower(), None) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1516 if not service: continue |
7874
d812029cda85
cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7071
diff
changeset
|
1517 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1518 if question.type == _TYPE_SRV or question.type == _TYPE_ANY: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1519 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
|
1520 if question.type == _TYPE_TXT or question.type == _TYPE_ANY: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1521 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
|
1522 if question.type == _TYPE_SRV: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1523 out.addAdditionalAnswer(DNSAddress(service.server, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address)) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1524 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1525 traceback.print_exc() |
7874
d812029cda85
cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7071
diff
changeset
|
1526 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1527 if out is not None and out.answers: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1528 out.id = msg.id |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1529 self.send(out, addr, port) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1530 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1531 def send(self, out, addr = _MDNS_ADDR, port = _MDNS_PORT): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1532 """Sends an outgoing packet.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1533 # 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
|
1534 #temp = DNSIncoming(out.packet()) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1535 try: |
7874
d812029cda85
cleanup: drop variables for unused return values
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7071
diff
changeset
|
1536 self.socket.sendto(out.packet(), 0, (addr, port)) |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1537 except: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1538 # Ignore this, it may be a temporary loss of network connection |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1539 pass |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1540 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1541 def close(self): |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1542 """Ends the background threads, and prevent this instance from |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1543 servicing further queries.""" |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1544 if globals()['_GLOBAL_DONE'] == 0: |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1545 globals()['_GLOBAL_DONE'] = 1 |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1546 self.notifyAll() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1547 self.engine.notify() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1548 self.unregisterAllServices() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1549 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
|
1550 self.socket.close() |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1551 |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1552 # Test a few module features, including service registration, service |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1553 # query (for Zoe), and service unregistration. |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1554 |
7877
eba7f12b0c51
cleanup: whitespace cleanup
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
7874
diff
changeset
|
1555 if __name__ == '__main__': |
7071
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1556 print "Multicast DNS Service Discovery for Python, version", __version__ |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1557 r = Zeroconf() |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1558 print "1. Testing registration of a service..." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1559 desc = {'version':'0.10','a':'test value', 'b':'another value'} |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1560 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
|
1561 print " Registering service..." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1562 r.registerService(info) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1563 print " Registration done." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1564 print "2. Testing query of service information..." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1565 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
|
1566 print " Query done." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1567 print "3. Testing query of own service..." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1568 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
|
1569 print " Query done." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1570 print "4. Testing unregister of service information..." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1571 r.unregisterService(info) |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1572 print " Unregister done." |
643c751e60b2
zeroconf: initial implementation
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1573 r.close() |