OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.names.test -*- | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 | |
6 import socket | |
7 | |
8 from twisted.names import dns | |
9 from twisted.internet import defer, error | |
10 from twisted.python import failure | |
11 | |
12 EMPTY_RESULT = (), (), () | |
13 | |
14 class ResolverBase: | |
15 typeToMethod = None | |
16 | |
17 def __init__(self): | |
18 self.typeToMethod = {} | |
19 for (k, v) in typeToMethod.items(): | |
20 self.typeToMethod[k] = getattr(self, v) | |
21 | |
22 def query(self, query, timeout = None): | |
23 try: | |
24 return self.typeToMethod[query.type](str(query.name), timeout) | |
25 except KeyError, e: | |
26 return defer.fail(failure.Failure(NotImplementedError(str(self.__cla
ss__) + " " + str(query.type)))) | |
27 | |
28 def _lookup(self, name, cls, type, timeout): | |
29 return defer.fail(NotImplementedError("ResolverBase._lookup")) | |
30 | |
31 def lookupAddress(self, name, timeout = None): | |
32 """ | |
33 @see: twisted.names.client.lookupAddress | |
34 """ | |
35 return self._lookup(name, dns.IN, dns.A, timeout) | |
36 | |
37 def lookupIPV6Address(self, name, timeout = None): | |
38 """ | |
39 @see: twisted.names.client.lookupIPV6Address | |
40 """ | |
41 return self._lookup(name, dns.IN, dns.AAAA, timeout) | |
42 | |
43 def lookupAddress6(self, name, timeout = None): | |
44 """ | |
45 @see: twisted.names.client.lookupAddress6 | |
46 """ | |
47 return self._lookup(name, dns.IN, dns.A6, timeout) | |
48 | |
49 def lookupMailExchange(self, name, timeout = None): | |
50 """ | |
51 @see: twisted.names.client.lookupMailExchange | |
52 """ | |
53 return self._lookup(name, dns.IN, dns.MX, timeout) | |
54 | |
55 def lookupNameservers(self, name, timeout = None): | |
56 """ | |
57 @see: twisted.names.client.lookupNameservers | |
58 """ | |
59 return self._lookup(name, dns.IN, dns.NS, timeout) | |
60 | |
61 def lookupCanonicalName(self, name, timeout = None): | |
62 """ | |
63 @see: twisted.names.client.lookupCanonicalName | |
64 """ | |
65 return self._lookup(name, dns.IN, dns.CNAME, timeout) | |
66 | |
67 def lookupMailBox(self, name, timeout = None): | |
68 """ | |
69 @see: twisted.names.client.lookupMailBox | |
70 """ | |
71 return self._lookup(name, dns.IN, dns.MB, timeout) | |
72 | |
73 def lookupMailGroup(self, name, timeout = None): | |
74 """ | |
75 @see: twisted.names.client.lookupMailGroup | |
76 """ | |
77 return self._lookup(name, dns.IN, dns.MG, timeout) | |
78 | |
79 def lookupMailRename(self, name, timeout = None): | |
80 """ | |
81 @see: twisted.names.client.lookupMailRename | |
82 """ | |
83 return self._lookup(name, dns.IN, dns.MR, timeout) | |
84 | |
85 def lookupPointer(self, name, timeout = None): | |
86 """ | |
87 @see: twisted.names.client.lookupPointer | |
88 """ | |
89 return self._lookup(name, dns.IN, dns.PTR, timeout) | |
90 | |
91 def lookupAuthority(self, name, timeout = None): | |
92 """ | |
93 @see: twisted.names.client.lookupAuthority | |
94 """ | |
95 return self._lookup(name, dns.IN, dns.SOA, timeout) | |
96 | |
97 def lookupNull(self, name, timeout = None): | |
98 """ | |
99 @see: twisted.names.client.lookupNull | |
100 """ | |
101 return self._lookup(name, dns.IN, dns.NULL, timeout) | |
102 | |
103 def lookupWellKnownServices(self, name, timeout = None): | |
104 """ | |
105 @see: twisted.names.client.lookupWellKnownServices | |
106 """ | |
107 return self._lookup(name, dns.IN, dns.WKS, timeout) | |
108 | |
109 def lookupService(self, name, timeout = None): | |
110 """ | |
111 @see: twisted.names.client.lookupService | |
112 """ | |
113 return self._lookup(name, dns.IN, dns.SRV, timeout) | |
114 | |
115 def lookupHostInfo(self, name, timeout = None): | |
116 """ | |
117 @see: twisted.names.client.lookupHostInfo | |
118 """ | |
119 return self._lookup(name, dns.IN, dns.HINFO, timeout) | |
120 | |
121 def lookupMailboxInfo(self, name, timeout = None): | |
122 """ | |
123 @see: twisted.names.client.lookupMailboxInfo | |
124 """ | |
125 return self._lookup(name, dns.IN, dns.MINFO, timeout) | |
126 | |
127 def lookupText(self, name, timeout = None): | |
128 """ | |
129 @see: twisted.names.client.lookupText | |
130 """ | |
131 return self._lookup(name, dns.IN, dns.TXT, timeout) | |
132 | |
133 def lookupResponsibility(self, name, timeout = None): | |
134 """ | |
135 @see: twisted.names.client.lookupResponsibility | |
136 """ | |
137 return self._lookup(name, dns.IN, dns.RP, timeout) | |
138 | |
139 def lookupAFSDatabase(self, name, timeout = None): | |
140 """ | |
141 @see: twisted.names.client.lookupAFSDatabase | |
142 """ | |
143 return self._lookup(name, dns.IN, dns.AFSDB, timeout) | |
144 | |
145 def lookupZone(self, name, timeout = None): | |
146 """ | |
147 @see: twisted.names.client.lookupZone | |
148 """ | |
149 return self._lookup(name, dns.IN, dns.AXFR, timeout) | |
150 | |
151 def lookupAllRecords(self, name, timeout = None): | |
152 """ | |
153 @see: twisted.names.client.lookupAllRecords | |
154 """ | |
155 return self._lookup(name, dns.IN, dns.ALL_RECORDS, timeout) | |
156 | |
157 def getHostByName(self, name, timeout = None, effort = 10): | |
158 """ | |
159 @see: twisted.names.client.getHostByName | |
160 """ | |
161 # XXX - respect timeout | |
162 return self.lookupAllRecords(name, timeout | |
163 ).addCallback(self._cbRecords, name, effort | |
164 ) | |
165 | |
166 def _cbRecords(self, (ans, auth, add), name, effort): | |
167 result = extractRecord(self, dns.Name(name), ans + auth + add, effort) | |
168 if not result: | |
169 raise error.DNSLookupError(name) | |
170 return result | |
171 | |
172 def extractRecord(resolver, name, answers, level = 10): | |
173 if not level: | |
174 return None | |
175 if hasattr(socket, 'inet_ntop'): | |
176 for r in answers: | |
177 if r.name == name and r.type == dns.A6: | |
178 return socket.inet_ntop(socket.AF_INET6, r.payload.address) | |
179 for r in answers: | |
180 if r.name == name and r.type == dns.AAAA: | |
181 return socket.inet_ntop(socket.AF_INET6, r.payload.address) | |
182 for r in answers: | |
183 if r.name == name and r.type == dns.A: | |
184 return socket.inet_ntop(socket.AF_INET, r.payload.address) | |
185 for r in answers: | |
186 if r.name == name and r.type == dns.CNAME: | |
187 result = extractRecord(resolver, r.payload.name, answers, level - 1) | |
188 if not result: | |
189 return resolver.getHostByName(str(r.payload.name), effort=level-
1) | |
190 return result | |
191 # No answers, but maybe there's a hint at who we should be asking about this | |
192 for r in answers: | |
193 if r.type == dns.NS: | |
194 from twisted.names import client | |
195 r = client.Resolver(servers=[(str(r.payload.name), dns.PORT)]) | |
196 return r.lookupAddress(str(name) | |
197 ).addCallback(lambda (ans, auth, add): extractRecord(r, name, an
s + auth + add, level - 1) | |
198 ).addBoth(lambda passthrough: (r.protocol.transport.stopListenin
g(), passthrough)[1]) | |
199 | |
200 typeToMethod = { | |
201 dns.A: 'lookupAddress', | |
202 dns.AAAA: 'lookupIPV6Address', | |
203 dns.A6: 'lookupAddress6', | |
204 dns.NS: 'lookupNameservers', | |
205 dns.CNAME: 'lookupCanonicalName', | |
206 dns.SOA: 'lookupAuthority', | |
207 dns.MB: 'lookupMailBox', | |
208 dns.MG: 'lookupMailGroup', | |
209 dns.MR: 'lookupMailRename', | |
210 dns.NULL: 'lookupNull', | |
211 dns.WKS: 'lookupWellKnownServices', | |
212 dns.PTR: 'lookupPointer', | |
213 dns.HINFO: 'lookupHostInfo', | |
214 dns.MINFO: 'lookupMailboxInfo', | |
215 dns.MX: 'lookupMailExchange', | |
216 dns.TXT: 'lookupText', | |
217 | |
218 dns.RP: 'lookupResponsibility', | |
219 dns.AFSDB: 'lookupAFSDatabase', | |
220 dns.SRV: 'lookupService', | |
221 | |
222 dns.AXFR: 'lookupZone', | |
223 dns.ALL_RECORDS: 'lookupAllRecords', | |
224 } | |
OLD | NEW |