Mailinglist Archive: opensuse-commit (2092 mails)
| < Previous | Next > |
commit python-twisted-names
- From: root@xxxxxxxxxxxxxxx (h_root)
- Date: Thu, 02 Aug 2007 23:33:05 +0200
- Message-id: <20070802213306.024966781B8@xxxxxxxxxxxxxxx>
Hello community,
here is the log from the commit of package python-twisted-names
checked in at Thu Aug 2 23:33:05 CEST 2007.
--------
--- python-twisted-names/python-twisted-names.changes 2006-10-26 18:35:40.000000000 +0200
+++ /mounts/work_src_done/STABLE/python-twisted-names/python-twisted-names.changes 2007-08-02 17:09:46.000000000 +0200
@@ -1,0 +2,8 @@
+Thu Aug 2 17:09:01 CEST 2007 - jmatejek@xxxxxxx
+
+- update to 0.4.0
+ * support for DNS error handling
+ * fixed DoS in UDP DNS server
+ * minor bugfixes
+
+-------------------------------------------------------------------
Old:
----
TwistedNames-0.3.0.tar.bz2
New:
----
TwistedNames-0.4.0.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-twisted-names.spec ++++++
--- /var/tmp/diff_new_pack.x19065/_old 2007-08-02 23:32:49.000000000 +0200
+++ /var/tmp/diff_new_pack.x19065/_new 2007-08-02 23:32:49.000000000 +0200
@@ -1,7 +1,7 @@
#
-# spec file for package python-twisted-names (Version 0.3.0)
+# spec file for package python-twisted-names (Version 0.4.0)
#
-# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany.
# This file and all modifications and additions to the pristine
# package are under the same license as the package itself.
#
@@ -13,7 +13,7 @@
Name: python-twisted-names
BuildRequires: python-devel python-twisted
Summary: Twisted Names
-Version: 0.3.0
+Version: 0.4.0
Release: 1
%define tarname TwistedNames
Source: %{tarname}-%{version}.tar.bz2
@@ -58,7 +58,12 @@
%defattr(-,root,root)
%doc LICENSE README NEWS
-%changelog -n python-twisted-names
+%changelog
+* Thu Aug 02 2007 - jmatejek@xxxxxxx
+- update to 0.4.0
+ * support for DNS error handling
+ * fixed DoS in UDP DNS server
+ * minor bugfixes
* Thu Oct 26 2006 - jmatejek@xxxxxxx
- update to 0.3.0
- upgrade to Twisted 2.4 install system
++++++ TwistedNames-0.3.0.tar.bz2 -> TwistedNames-0.4.0.tar.bz2 ++++++
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/doc/examples/dns-service.py new/TwistedNames-0.4.0/doc/examples/dns-service.py
--- old/TwistedNames-0.3.0/doc/examples/dns-service.py 2004-07-30 14:01:15.000000000 +0200
+++ new/TwistedNames-0.4.0/doc/examples/dns-service.py 2006-12-29 06:01:40.000000000 +0100
@@ -25,7 +25,7 @@
sys.exit(1)
resolver = client.Resolver('/etc/resolv.conf')
-d = resolver.lookupService('_%s._%s.%s' % (service, proto, domain), 1)
+d = resolver.lookupService('_%s._%s.%s' % (service, proto, domain), [1])
d.addCallbacks(printAnswer, printFailure)
reactor.run()
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/doc/examples/gethostbyname.py new/TwistedNames-0.4.0/doc/examples/gethostbyname.py
--- old/TwistedNames-0.3.0/doc/examples/gethostbyname.py 2004-07-30 14:01:15.000000000 +0200
+++ new/TwistedNames-0.4.0/doc/examples/gethostbyname.py 2006-12-29 06:01:40.000000000 +0100
@@ -12,7 +12,7 @@
failure.printTraceback()
reactor.stop()
-gethostbyname = client.theResolver.getHostByName
-gethostbyname(sys.argv[1]).addCallbacks(gotResult, gotFailure)
+d = client.getHostByName(sys.argv[1])
+d.addCallbacks(gotResult, gotFailure)
reactor.run()
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/doc/examples/index.html new/TwistedNames-0.4.0/doc/examples/index.html
--- old/TwistedNames-0.3.0/doc/examples/index.html 2006-05-25 03:08:23.000000000 +0200
+++ new/TwistedNames-0.4.0/doc/examples/index.html 2007-01-07 03:43:17.000000000 +0100
@@ -1,2 +1,2 @@
<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Twisted Names code examples</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Twisted Names code examples</h1><div class="toc"><ol><li><a href="#auto0">DNS (Twisted Names)</a></li></ol></div><div class="content"><span></span><h2>DNS (Twisted Names)<a name="auto0"></a></h2><ul><li><a href="testdns.py">testdns.py</a></li><li><a href="dns-service.py">dns-service.py</a></li><li><a href="gethostbyname.py">gethostbyname.py</a></li></ul></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 0.3.0</span></body></html>
\ No newline at end of file
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Twisted Names code examples</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Twisted Names code examples</h1><div class="toc"><ol><li><a href="#auto0">DNS (Twisted Names)</a></li></ol></div><div class="content"><span></span><h2>DNS (Twisted Names)<a name="auto0"></a></h2><ul><li><a href="testdns.py">testdns.py</a></li><li><a href="dns-service.py">dns-service.py</a></li><li><a href="gethostbyname.py">gethostbyname.py</a></li></ul></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 0.4.0</span></body></html>
\ No newline at end of file
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/doc/examples/testdns.py new/TwistedNames-0.4.0/doc/examples/testdns.py
--- old/TwistedNames-0.3.0/doc/examples/testdns.py 2004-07-30 14:01:15.000000000 +0200
+++ new/TwistedNames-0.4.0/doc/examples/testdns.py 2006-07-02 05:53:32.000000000 +0200
@@ -3,7 +3,7 @@
import sys
from twisted.names import client
from twisted.internet import reactor
-from twisted.protocols import dns
+from twisted.names import dns
r = client.Resolver('/etc/resolv.conf')
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/doc/howto/index.html new/TwistedNames-0.4.0/doc/howto/index.html
--- old/TwistedNames-0.3.0/doc/howto/index.html 2006-05-25 03:08:22.000000000 +0200
+++ new/TwistedNames-0.4.0/doc/howto/index.html 2007-01-07 03:43:17.000000000 +0100
@@ -1,2 +1,2 @@
<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Twisted Names Documentation</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Twisted Names Documentation</h1><div class="toc"><ol></ol></div><div class="content"><span></span><ul class="toc"><li><a href="names.html">Names DNS library</a></li></ul></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 0.3.0</span></body></html>
\ No newline at end of file
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Twisted Names Documentation</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Twisted Names Documentation</h1><div class="toc"><ol></ol></div><div class="content"><span></span><ul class="toc"><li><a href="names.html">Names DNS library</a></li></ul></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 0.4.0</span></body></html>
\ No newline at end of file
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/doc/howto/names.html new/TwistedNames-0.4.0/doc/howto/names.html
--- old/TwistedNames-0.3.0/doc/howto/names.html 2006-05-25 03:08:23.000000000 +0200
+++ new/TwistedNames-0.4.0/doc/howto/names.html 2007-01-07 03:43:17.000000000 +0100
@@ -3,8 +3,7 @@
<ul><li>act as a recursive server, forwarding queries to other servers</li><li>perform local caching of recursively discovered records</li><li>act as the authoritative server for a domain</li></ul><h3>Creating a non-authoritative server<a name="auto0"></a></h3>
The first two of these are easy, and you can create a server that performs
them with the command <code class="shell">mktap dns --recursive
---cache</code>, or launch <code class="shell">tkmktap</code> and configure a
-dns server with it. The result should be a file named <code>dns.tap</code>.
+--cache</code>. The result should be a file named <code>dns.tap</code>.
Now switch to a superuser account (if required by your platform to bind to
port 53) and run <code class="shell">twistd -f dns.tap</code>. The
Application will run and bind to port 53. Try performing a lookup with it,
@@ -60,4 +59,4 @@
</p><p>Names can also read a traditional, BIND-syntax zone file. Specify these
with the <code>--bindzone</code> parameter. The $GENERATE and $INCLUDE
directives are not yet supported.
-</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 0.3.0</span></body></html>
\ No newline at end of file
+</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 0.4.0</span></body></html>
\ No newline at end of file
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/LICENSE new/TwistedNames-0.4.0/LICENSE
--- old/TwistedNames-0.3.0/LICENSE 2006-04-18 04:43:54.000000000 +0200
+++ new/TwistedNames-0.4.0/LICENSE 2006-06-03 22:59:55.000000000 +0200
@@ -6,6 +6,7 @@
Bob Ippolito
Canonical Limited
Christopher Armstrong
+David Reid
Donovan Preston
Eric Mangold
Itamar Shtull-Trauring
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/NEWS new/TwistedNames-0.4.0/NEWS
--- old/TwistedNames-0.3.0/NEWS 2006-05-22 00:28:51.000000000 +0200
+++ new/TwistedNames-0.4.0/NEWS 2007-01-06 22:50:02.000000000 +0100
@@ -1,3 +1,23 @@
+0.4.0 (2007-01-06)
+==================
+
+Features
+--------
+
+ - In the twisted.names client, DNS responses which represent errors
+ are now translated to informative exception objects, rather than
+ empty lists. This means that client requests which fail will now
+ errback their Deferreds (#2248)
+
+Fixes
+-----
+ - A major DoS vulnerability in the UDP DNS server was fixed (#1708)
+
+Misc
+----
+ - #1799, #1636, #2149, #2181
+
+
0.3.0 (2006-05-21)
==================
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/README new/TwistedNames-0.4.0/README
--- old/TwistedNames-0.3.0/README 2006-05-22 00:28:51.000000000 +0200
+++ new/TwistedNames-0.4.0/README 2007-01-06 22:42:54.000000000 +0100
@@ -1,3 +1,3 @@
-Twisted Names 0.3.0
+Twisted Names 0.4.0
Twisted Names depends on Twisted Core.
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/cache.py new/TwistedNames-0.4.0/twisted/names/cache.py
--- old/TwistedNames-0.3.0/twisted/names/cache.py 2006-03-17 04:29:41.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/cache.py 2006-07-01 18:08:17.000000000 +0200
@@ -8,7 +8,7 @@
from zope.interface import implements
from twisted.names import dns
-from twisted.python import failure, log, components
+from twisted.python import failure, log
from twisted.internet import interfaces, defer
import common
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/client.py new/TwistedNames-0.4.0/twisted/names/client.py
--- old/TwistedNames-0.3.0/twisted/names/client.py 2006-03-17 04:29:41.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/client.py 2006-12-29 06:01:40.000000000 +0100
@@ -1,5 +1,5 @@
# -*- test-case-name: twisted.names.test.test_names -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
+# Copyright (c) 2001-2006 Twisted Matrix Laboratories.
# See LICENSE for details.
@@ -8,6 +8,13 @@
API Stability: Unstable
+The functions exposed in this module can be used for asynchronous name
+resolution and dns queries.
+
+If you need to create a resolver with specific requirements, such as needing to
+do queries against a particular host, the L{createResolver} function will
+return an C{IResolver}.
+
Future plans: Proper nameserver acquisition on Windows/MacOS,
better caching, respect timeouts
@@ -19,13 +26,17 @@
import os
import errno
+from zope.interface import implements
+
# Twisted imports
from twisted.python.runtime import platform
from twisted.internet import error, defer, protocol, interfaces
-from twisted.python import log, failure, components
-from twisted.names import dns
-from zope.interface import implements
-import common
+from twisted.python import log, failure
+from twisted.names import dns, common
+from twisted.names.error import DNSFormatError, DNSServerError, DNSNameError
+from twisted.names.error import DNSNotImplementedError, DNSQueryRefusedError
+from twisted.names.error import DNSUnknownError
+
class Resolver(common.ResolverBase):
implements(interfaces.IResolver)
@@ -44,6 +55,13 @@
_lastResolvTime = None
_resolvReadInterval = 60
+ _errormap = {
+ dns.EFORMAT: DNSFormatError,
+ dns.ESERVER: DNSServerError,
+ dns.ENAME: DNSNameError,
+ dns.ENOTIMP: DNSNotImplementedError,
+ dns.EREFUSED: DNSQueryRefusedError}
+
def __init__(self, resolv = None, servers = None, timeout = (1, 3, 11, 45)):
"""
Construct a resolver which will query domain name servers listed in
@@ -53,7 +71,7 @@
for modification and re-parsed if it is noticed to have changed.
@type servers: C{list} of C{(str, int)} or C{None}
- @param servers: If not None, interpreted as a list of addresses of
+ @param servers: If not C{None}, interpreted as a list of addresses of
domain name servers to attempt to use for this lookup. Addresses
should be in dotted-quad form. If specified, overrides C{resolv}.
@@ -271,10 +289,23 @@
def filterAnswers(self, message):
+ """
+ Extract results from the given message.
+
+ If the message was truncated, re-attempt the query over TCP and return
+ a Deferred which will fire with the results of that query.
+
+ If the message's result code is not L{dns.OK}, return a Failure
+ indicating the type of error which occurred.
+
+ Otherwise, return a three-tuple of lists containing the results from
+ the answers section, the authority section, and the additional section.
+ """
if message.trunc:
return self.queryTCP(message.queries).addCallback(self.filterAnswers)
- else:
- return (message.answers, message.authority, message.additional)
+ if message.rCode != dns.OK:
+ return failure.Failure(self._errormap.get(message.rCode, DNSUnknownError)(message))
+ return (message.answers, message.authority, message.additional)
def _lookup(self, name, cls, type, timeout):
@@ -385,7 +416,27 @@
-def createResolver(servers = None, resolvconf = None, hosts = None):
+def createResolver(servers=None, resolvconf=None, hosts=None):
+ """
+ Create and return a Resolver.
+
+ @type servers: C{list} of C{(str, int)} or C{None}
+ @param servers: If not C{None}, interpreted as a list of addresses of
+ domain name servers to attempt to use. Addresses should be in dotted-quad
+ form.
+
+ @type resolvconf: C{str} or C{None}
+ @param resolvconf: If not C{None}, on posix systems will be interpreted as
+ an alternate resolv.conf to use. Will do nothing on windows systems. If
+ C{None}, /etc/resolv.conf will be used.
+
+ @type hosts: C{str} or C{None}
+ @param hosts: If not C{None}, an alternate hosts file to use. If C{None}
+ on posix systems, /etc/hosts will be used. On windows, C:\windows\hosts
+ will be used.
+
+ @rtype: C{IResolver}
+ """
from twisted.names import resolve, cache, root, hosts as hostsModule
if platform.getType() == 'posix':
if resolvconf is None:
@@ -406,20 +457,357 @@
return resolve.ResolverChain(L)
theResolver = None
-def _makeLookup(method):
- def lookup(*a, **kw):
- global theResolver
- if theResolver is None:
- try:
- theResolver = createResolver()
- except ValueError:
- theResolver = createResolver(servers=[('127.0.0.1', 53)])
-
- return getattr(theResolver, method)(*a, **kw)
- return lookup
-
-for method in common.typeToMethod.values():
- globals()[method] = _makeLookup(method)
-del method
+def getResolver():
+ """
+ Get a Resolver instance.
+
+ Create twisted.names.client.theResolver if it is C{None}, and then return
+ that value.
+
+ @rtype: C{IResolver}
+ """
+ global theResolver
+ if theResolver is None:
+ try:
+ theResolver = createResolver()
+ except ValueError:
+ theResolver = createResolver(servers=[('127.0.0.1', 53)])
+ return theResolver
+
+def getHostByName(name, timeout=None, effort=10):
+ """
+ Resolve a name to a valid ipv4 or ipv6 address.
+
+ Will errback with C{DNSQueryTimeoutError} on a timeout, C{DomainError} or
+ C{AuthoritativeDomainError} (or subclasses) on other errors.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @type effort: C{int}
+ @param effort: How many times CNAME and NS records to follow while
+ resolving this name.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().getHostByName(name, timeout, effort)
+
+def lookupAddress(name, timeout=None):
+ """
+ Perform an A record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupAddress(name, timeout)
+
+def lookupIPV6Address(name, timeout=None):
+ """
+ Perform an AAAA record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupIPV6Address(name, timeout)
+
+def lookupAddress6(name, timeout=None):
+ """
+ Perform an A6 record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupAddress6(name, timeout)
+
+def lookupMailExchange(name, timeout=None):
+ """
+ Perform an MX record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupMailExchange(name, timeout)
+
+def lookupNameservers(name, timeout=None):
+ """
+ Perform an NS record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupNameservers(name, timeout)
+
+def lookupCanonicalName(name, timeout=None):
+ """
+ Perform a CNAME record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupCanonicalName(name, timeout)
+
+def lookupMailBox(name, timeout=None):
+ """
+ Perform an MB record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupMailBox(name, timeout)
+
+def lookupMailGroup(name, timeout=None):
+ """
+ Perform an MG record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupMailGroup(name, timeout)
+
+def lookupMailRename(name, timeout=None):
+ """
+ Perform an MR record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupMailRename(name, timeout)
+
+def lookupPointer(name, timeout=None):
+ """
+ Perform a PTR record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupPointer(name, timeout)
+
+def lookupAuthority(name, timeout=None):
+ """
+ Perform an SOA record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupAuthority(name, timeout)
+
+def lookupNull(name, timeout=None):
+ """
+ Perform a NULL record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupNull(name, timeout)
+
+def lookupWellKnownServices(name, timeout=None):
+ """
+ Perform a WKS record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupWellKnownServices(name, timeout)
+
+def lookupService(name, timeout=None):
+ """
+ Perform an SRV record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupService(name, timeout)
+
+def lookupHostInfo(name, timeout=None):
+ """
+ Perform a HINFO record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupHostInfo(name, timeout)
+
+def lookupMailboxInfo(name, timeout=None):
+ """
+ Perform an MINFO record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupMailboxInfo(name, timeout)
+
+def lookupText(name, timeout=None):
+ """
+ Perform a TXT record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupText(name, timeout)
+
+def lookupResponsibility(name, timeout=None):
+ """
+ Perform an RP record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupResponsibility(name, timeout)
+
+def lookupAFSDatabase(name, timeout=None):
+ """
+ Perform an AFSDB record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupAFSDatabase(name, timeout)
+
+def lookupZone(name, timeout=None):
+ """
+ Perform an AXFR record lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: C{int}
+ @param timeout: When this timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ # XXX: timeout here is not a list of ints, it is a single int.
+ return getResolver().lookupZone(name, timeout)
+
+def lookupAllRecords(name, timeout=None):
+ """
+ ALL_RECORD lookup.
+
+ @type name: C{str}
+ @param name: DNS name to resolve.
+
+ @type timeout: Sequence of C{int}
+ @param timeout: Number of seconds after which to reissue the query.
+ When the last timeout expires, the query is considered failed.
+
+ @rtype: C{Deferred}
+ """
+ return getResolver().lookupAllRecords(name, timeout)
-getHostByName = _makeLookup('getHostByName')
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/common.py new/TwistedNames-0.4.0/twisted/names/common.py
--- old/TwistedNames-0.3.0/twisted/names/common.py 2006-03-17 04:29:41.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/common.py 2006-12-29 06:01:40.000000000 +0100
@@ -29,69 +29,135 @@
return defer.fail(NotImplementedError("ResolverBase._lookup"))
def lookupAddress(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupAddress
+ """
return self._lookup(name, dns.IN, dns.A, timeout)
def lookupIPV6Address(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupIPV6Address
+ """
return self._lookup(name, dns.IN, dns.AAAA, timeout)
def lookupAddress6(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupAddress6
+ """
return self._lookup(name, dns.IN, dns.A6, timeout)
def lookupMailExchange(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupMailExchange
+ """
return self._lookup(name, dns.IN, dns.MX, timeout)
def lookupNameservers(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupNameservers
+ """
return self._lookup(name, dns.IN, dns.NS, timeout)
def lookupCanonicalName(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupCanonicalName
+ """
return self._lookup(name, dns.IN, dns.CNAME, timeout)
def lookupMailBox(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupMailBox
+ """
return self._lookup(name, dns.IN, dns.MB, timeout)
def lookupMailGroup(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupMailGroup
+ """
return self._lookup(name, dns.IN, dns.MG, timeout)
def lookupMailRename(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupMailRename
+ """
return self._lookup(name, dns.IN, dns.MR, timeout)
def lookupPointer(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupPointer
+ """
return self._lookup(name, dns.IN, dns.PTR, timeout)
def lookupAuthority(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupAuthority
+ """
return self._lookup(name, dns.IN, dns.SOA, timeout)
def lookupNull(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupNull
+ """
return self._lookup(name, dns.IN, dns.NULL, timeout)
def lookupWellKnownServices(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupWellKnownServices
+ """
return self._lookup(name, dns.IN, dns.WKS, timeout)
def lookupService(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupService
+ """
return self._lookup(name, dns.IN, dns.SRV, timeout)
def lookupHostInfo(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupHostInfo
+ """
return self._lookup(name, dns.IN, dns.HINFO, timeout)
def lookupMailboxInfo(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupMailboxInfo
+ """
return self._lookup(name, dns.IN, dns.MINFO, timeout)
def lookupText(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupText
+ """
return self._lookup(name, dns.IN, dns.TXT, timeout)
def lookupResponsibility(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupResponsibility
+ """
return self._lookup(name, dns.IN, dns.RP, timeout)
def lookupAFSDatabase(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupAFSDatabase
+ """
return self._lookup(name, dns.IN, dns.AFSDB, timeout)
def lookupZone(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupZone
+ """
return self._lookup(name, dns.IN, dns.AXFR, timeout)
def lookupAllRecords(self, name, timeout = None):
+ """
+ @see: twisted.names.client.lookupAllRecords
+ """
return self._lookup(name, dns.IN, dns.ALL_RECORDS, timeout)
def getHostByName(self, name, timeout = None, effort = 10):
+ """
+ @see: twisted.names.client.getHostByName
+ """
# XXX - respect timeout
return self.lookupAllRecords(name, timeout
).addCallback(self._cbRecords, name, effort
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/dns.py new/TwistedNames-0.4.0/twisted/names/dns.py
--- old/TwistedNames-0.3.0/twisted/names/dns.py 2006-03-17 04:29:41.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/dns.py 2006-12-06 04:15:37.000000000 +0100
@@ -43,7 +43,6 @@
return struct.unpack('H', r(2))[0]
break
else:
- import warnings
warnings.warn(
"PyCrypto not available - proceeding with non-cryptographically "
"secure random source",
@@ -56,55 +55,80 @@
else:
def randomSource(r = randpool.RandomPool().get_bytes):
return struct.unpack('H', r(2))[0]
-from zope.interface import implements
+from zope.interface import implements, Interface
# Twisted imports
from twisted.internet import protocol, defer
from twisted.python import log, failure
from twisted.python import util as tputil
-from twisted.python import components
PORT = 53
+(A, NS, MD, MF, CNAME, SOA, MB, MG, MR, NULL, WKS, PTR, HINFO, MINFO, MX, TXT,
+ RP, AFSDB) = range(1, 19)
+AAAA = 28
+SRV = 33
+A6 = 38
+DNAME = 39
+
QUERY_TYPES = {
- 1: 'A', 2: 'NS', 3: 'MD', 4: 'MF',
- 5: 'CNAME', 6: 'SOA', 7: 'MB', 8: 'MG',
- 9: 'MR', 10: 'NULL', 11: 'WKS', 12: 'PTR',
- 13: 'HINFO', 14: 'MINFO', 15: 'MX', 16: 'TXT',
+ A: 'A',
+ NS: 'NS',
+ MD: 'MD',
+ MF: 'MF',
+ CNAME: 'CNAME',
+ SOA: 'SOA',
+ MB: 'MB',
+ MG: 'MG',
+ MR: 'MR',
+ NULL: 'NULL',
+ WKS: 'WKS',
+ PTR: 'PTR',
+ HINFO: 'HINFO',
+ MINFO: 'MINFO',
+ MX: 'MX',
+ TXT: 'TXT',
+ RP: 'RP',
+ AFSDB: 'AFSDB',
- 17: 'RP', 18: 'AFSDB',
# 19 through 27? Eh, I'll get to 'em.
- 28: 'AAAA',
-
- 33: 'SRV',
+ AAAA: 'AAAA',
+ SRV: 'SRV',
- 38: 'A6', 39: 'DNAME'
+ A6: 'A6',
+ DNAME: 'DNAME'
}
+IXFR, AXFR, MAILB, MAILA, ALL_RECORDS = range(251, 256)
+
# "Extended" queries (Hey, half of these are deprecated, good job)
EXT_QUERIES = {
- 251: 'IXFR', 252: 'AXFR', 253: 'MAILB',
- 254: 'MAILA', 255: 'ALL_RECORDS'
+ IXFR: 'IXFR',
+ AXFR: 'AXFR',
+ MAILB: 'MAILB',
+ MAILA: 'MAILA',
+ ALL_RECORDS: 'ALL_RECORDS'
}
+
REV_TYPES = dict([
(v, k) for (k, v) in QUERY_TYPES.items() + EXT_QUERIES.items()
])
-for (k, v) in REV_TYPES.items():
- exec "%s = %d" % (k, v)
-del k, v
+IN, CS, CH, HS = range(1, 5)
+ANY = 255
QUERY_CLASSES = {
- 1: 'IN', 2: 'CS', 3: 'CH', 4: 'HS', 255: 'ANY'
+ IN: 'IN',
+ CS: 'CS',
+ CH: 'CH',
+ HS: 'HS',
+ ANY: 'ANY'
}
REV_CLASSES = dict([
(v, k) for (k, v) in QUERY_CLASSES.items()
])
-for (k, v) in REV_CLASSES.items():
- exec "%s = %d" % (k, v)
-del k, v
# Opcodes
@@ -113,22 +137,18 @@
# Response Codes
OK, EFORMAT, ESERVER, ENAME, ENOTIMP, EREFUSED = range(6)
-class IRecord(components.Interface):
+class IRecord(Interface):
"""An single entry in a zone of authority.
@cvar TYPE: An indicator of what kind of record this is.
"""
-class DomainError(ValueError):
- pass
-class AuthoritativeDomainError(ValueError):
- pass
+# Backwards compatibility aliases - these should be deprecated or something I
+# suppose. -exarkun
+from twisted.names.error import DomainError, AuthoritativeDomainError
+from twisted.names.error import DNSQueryTimeoutError
-class DNSQueryTimeoutError(defer.TimeoutError):
- def __init__(self, id):
- self.id = id
- defer.TimeoutError.__init__(self)
def str2time(s):
suffixes = (
@@ -154,12 +174,12 @@
return buff
-class IEncodable(components.Interface):
+class IEncodable(Interface):
"""
Interface for something which can be encoded to and decoded
from a file object.
"""
- def encode(self, strio, compDict = None):
+ def encode(strio, compDict = None):
"""
Write a representation of this object to the given
file object.
@@ -173,7 +193,7 @@
compression.
"""
- def decode(self, strio, length = None):
+ def decode(strio, length = None):
"""
Reconstruct an object from data read from the given
file object.
@@ -1085,7 +1105,19 @@
def datagramReceived(self, data, addr):
m = Message()
- m.fromStr(data)
+ try:
+ m.fromStr(data)
+ except EOFError:
+ log.msg("Truncated packet (%d bytes) from %s" % (len(data), addr))
+ return
+ except:
+ # Nothing should trigger this, but since we're potentially
+ # invoking a lot of different decoding methods, we might as well
+ # be extra cautious. Anything that triggers this is itself
+ # buggy.
+ log.err(failure.Failure(), "Unexpected decoding error")
+ return
+
if m.id in self.liveMessages:
d, canceller = self.liveMessages[m.id]
del self.liveMessages[m.id]
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/error.py new/TwistedNames-0.4.0/twisted/names/error.py
--- old/TwistedNames-0.3.0/twisted/names/error.py 1970-01-01 01:00:00.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/error.py 2006-12-06 04:15:37.000000000 +0100
@@ -0,0 +1,88 @@
+# -*- test-case-name: twisted.names.test -*-
+# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Exception class definitions for Twisted Names.
+"""
+
+from twisted.internet.defer import TimeoutError
+
+
+class DomainError(ValueError):
+ """
+ Indicates a lookup failed because there were no records matching the given
+ C{name, class, type} triple.
+ """
+
+
+
+class AuthoritativeDomainError(ValueError):
+ """
+ Indicates a lookup failed for a name for which this server is authoritative
+ because there were no records matching the given C{name, class, type}
+ triple.
+ """
+
+
+
+class DNSQueryTimeoutError(TimeoutError):
+ """
+ Indicates a lookup failed due to a timeout.
+
+ @ivar id: The id of the message which timed out.
+ """
+ def __init__(self, id):
+ TimeoutError.__init__(self)
+ self.id = id
+
+
+
+class DNSFormatError(DomainError):
+ """
+ Indicates a query failed with a result of L{twisted.names.dns.EFORMAT}.
+ """
+
+
+
+class DNSServerError(DomainError):
+ """
+ Indicates a query failed with a result of L{twisted.names.dns.ESERVER}.
+ """
+
+
+
+class DNSNameError(DomainError):
+ """
+ Indicates a query failed with a result of L{twisted.names.dns.ENAME}.
+ """
+
+
+
+class DNSNotImplementedError(DomainError):
+ """
+ Indicates a query failed with a result of L{twisted.names.dns.ENOTIMP}.
+ """
+
+
+
+class DNSQueryRefusedError(DomainError):
+ """
+ Indicates a query failed with a result of L{twisted.names.dns.EREFUSED}.
+ """
+
+
+
+class DNSUnknownError(DomainError):
+ """
+ Indicates a query failed with an unknown result.
+ """
+
+
+
+__all__ = [
+ 'DomainError', 'AuthoritativeDomainError', 'DNSQueryTimeoutError',
+
+ 'DNSFormatError', 'DNSServerError', 'DNSNameError',
+ 'DNSNotImplementedError', 'DNSQueryRefusedError',
+ 'DNSUnknownError']
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/resolve.py new/TwistedNames-0.4.0/twisted/names/resolve.py
--- old/TwistedNames-0.3.0/twisted/names/resolve.py 2006-03-17 04:29:41.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/resolve.py 2006-07-01 18:08:17.000000000 +0200
@@ -15,7 +15,6 @@
from twisted.internet import defer, interfaces
from twisted.names import dns
-from twisted.python import components
from zope.interface import implements
import common
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/test/test_client.py new/TwistedNames-0.4.0/twisted/names/test/test_client.py
--- old/TwistedNames-0.3.0/twisted/names/test/test_client.py 1970-01-01 01:00:00.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/test/test_client.py 2006-12-29 06:01:40.000000000 +0100
@@ -0,0 +1,241 @@
+# -*- test-case-name: twisted.names.test.test_client -*-
+# Copyright (c) 2001-2006 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Test cases for twisted.names.client
+"""
+
+from twisted.names import client, dns
+from twisted.trial import unittest
+from twisted.names.common import ResolverBase
+from twisted.internet import defer
+
+class FakeResolver(ResolverBase):
+
+ def _lookup(self, name, cls, qtype, timeout):
+ """
+ The getHostByNameTest does a different type of query that requires it
+ return an A record from an ALL_RECORDS lookup, so we accomodate that
+ here.
+ """
+ if name == 'getHostByNameTest':
+ rr = dns.RRHeader(name=name, type=dns.A, cls=cls, ttl=60,
+ payload=dns.Record_A(address='127.0.0.1', ttl=60))
+ else:
+ rr = dns.RRHeader(name=name, type=qtype, cls=cls, ttl=60)
+
+ results = [rr]
+ authority = []
+ addtional = []
+ return defer.succeed((results, authority, addtional))
+
+class ClientTestCase(unittest.TestCase):
+
+ def setUp(self):
+ """
+ Replace the resolver with a FakeResolver
+ """
+ client.theResolver = FakeResolver()
+ self.hostname = 'example.com'
+ self.ghbntest = 'getHostByNameTest'
+
+ def tearDown(self):
+ """
+ By setting the resolver to None, it will be recreated next time a name
+ lookup is done.
+ """
+ client.theResolver = None
+
+ def checkResult(self, (results, authority, additional), qtype):
+ """
+ Verify that the result is the same query type as what is expected.
+ """
+ result = results[0]
+ self.assertEquals(str(result.name), self.hostname)
+ self.assertEquals(result.type, qtype)
+
+ def checkGetHostByName(self, result):
+ """
+ Test that the getHostByName query returns the 127.0.0.1 address.
+ """
+ self.assertEquals(result, '127.0.0.1')
+
+ def test_getHostByName(self):
+ """
+ do a getHostByName of a value that should return 127.0.0.1.
+ """
+ d = client.getHostByName(self.ghbntest)
+ d.addCallback(self.checkGetHostByName)
+ return d
+
+ def test_lookupAddress(self):
+ """
+ Do a lookup and test that the resolver will issue the correct type of
+ query type. We do this by checking that FakeResolver returns a result
+ record with the same query type as what we issued.
+ """
+ d = client.lookupAddress(self.hostname)
+ d.addCallback(self.checkResult, dns.A)
+ return d
+
+ def test_lookupIPV6Address(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupIPV6Address(self.hostname)
+ d.addCallback(self.checkResult, dns.AAAA)
+ return d
+
+ def test_lookupAddress6(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupAddress6(self.hostname)
+ d.addCallback(self.checkResult, dns.A6)
+ return d
+
+ def test_lookupNameservers(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupNameservers(self.hostname)
+ d.addCallback(self.checkResult, dns.NS)
+ return d
+
+ def test_lookupCanonicalName(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupCanonicalName(self.hostname)
+ d.addCallback(self.checkResult, dns.CNAME)
+ return d
+
+ def test_lookupAuthority(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupAuthority(self.hostname)
+ d.addCallback(self.checkResult, dns.SOA)
+ return d
+
+ def test_lookupMailBox(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupMailBox(self.hostname)
+ d.addCallback(self.checkResult, dns.MB)
+ return d
+
+ def test_lookupMailGroup(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupMailGroup(self.hostname)
+ d.addCallback(self.checkResult, dns.MG)
+ return d
+
+ def test_lookupMailRename(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupMailRename(self.hostname)
+ d.addCallback(self.checkResult, dns.MR)
+ return d
+
+ def test_lookupNull(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupNull(self.hostname)
+ d.addCallback(self.checkResult, dns.NULL)
+ return d
+
+ def test_lookupWellKnownServices(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupWellKnownServices(self.hostname)
+ d.addCallback(self.checkResult, dns.WKS)
+ return d
+
+ def test_lookupPointer(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupPointer(self.hostname)
+ d.addCallback(self.checkResult, dns.PTR)
+ return d
+
+ def test_lookupHostInfo(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupHostInfo(self.hostname)
+ d.addCallback(self.checkResult, dns.HINFO)
+ return d
+
+ def test_lookupMailboxInfo(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupMailboxInfo(self.hostname)
+ d.addCallback(self.checkResult, dns.MINFO)
+ return d
+
+ def test_lookupMailExchange(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupMailExchange(self.hostname)
+ d.addCallback(self.checkResult, dns.MX)
+ return d
+
+ def test_lookupText(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupText(self.hostname)
+ d.addCallback(self.checkResult, dns.TXT)
+ return d
+
+ def test_lookupResponsibility(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupResponsibility(self.hostname)
+ d.addCallback(self.checkResult, dns.RP)
+ return d
+
+ def test_lookupAFSDatabase(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupAFSDatabase(self.hostname)
+ d.addCallback(self.checkResult, dns.AFSDB)
+ return d
+
+ def test_lookupService(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupService(self.hostname)
+ d.addCallback(self.checkResult, dns.SRV)
+ return d
+
+ def test_lookupZone(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupZone(self.hostname)
+ d.addCallback(self.checkResult, dns.AXFR)
+ return d
+
+ def test_lookupAllRecords(self):
+ """
+ See L{test_lookupAddress}
+ """
+ d = client.lookupAllRecords(self.hostname)
+ d.addCallback(self.checkResult, dns.ALL_RECORDS)
+ return d
+
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/test/test_dns.py new/TwistedNames-0.4.0/twisted/names/test/test_dns.py
--- old/TwistedNames-0.3.0/twisted/names/test/test_dns.py 2005-11-10 04:18:15.000000000 +0100
+++ new/TwistedNames-0.4.0/twisted/names/test/test_dns.py 2006-06-07 01:56:12.000000000 +0200
@@ -11,6 +11,7 @@
except ImportError:
from StringIO import StringIO
+from twisted.internet import address
from twisted.trial import unittest
from twisted.names import dns
@@ -95,7 +96,43 @@
self.assertEquals(hk1, hk2, "%s != %s (for %s)" % (hk1,hk2,k))
-class Encoding(unittest.TestCase):
+
+class MessageTestCase(unittest.TestCase):
+ def testEmptyMessage(self):
+ """
+ Test that a message which has been truncated causes an EOFError to
+ be raised when it is parsed.
+ """
+ msg = dns.Message()
+ self.assertRaises(EOFError, msg.fromStr, '')
+
+
+ def testEmptyQuery(self):
+ """
+ Test that bytes representing an empty query message can be decoded
+ as such.
+ """
+ msg = dns.Message()
+ msg.fromStr(
+ '\x01\x00' # Message ID
+ '\x00' # answer bit, opCode nibble, auth bit, trunc bit, recursive bit
+ '\x00' # recursion bit, empty bit, empty bit, empty bit, response code nibble
+ '\x00\x00' # number of queries
+ '\x00\x00' # number of answers
+ '\x00\x00' # number of authorities
+ '\x00\x00' # number of additionals
+ )
+ self.assertEquals(msg.id, 256)
+ self.failIf(msg.answer, "Message was not supposed to be an answer.")
+ self.assertEquals(msg.opCode, dns.OP_QUERY)
+ self.failIf(msg.auth, "Message was not supposed to be authoritative.")
+ self.failIf(msg.trunc, "Message was not supposed to be truncated.")
+ self.assertEquals(msg.queries, [])
+ self.assertEquals(msg.answers, [])
+ self.assertEquals(msg.authority, [])
+ self.assertEquals(msg.additional, [])
+
+
def testNULL(self):
bytes = ''.join([chr(i) for i in range(256)])
rec = dns.Record_NULL(bytes)
@@ -111,3 +148,32 @@
self.failUnless(isinstance(msg2.answers[0].payload, dns.Record_NULL))
self.assertEquals(msg2.answers[0].payload.payload, bytes)
+
+
+class TestController(object):
+ """
+ Pretend to be a DNS query processor for a DNSDatagramProtocol.
+ """
+ def __init__(self):
+ self.messages = []
+
+
+ def messageReceived(self, msg, proto, addr):
+ self.messages.append((msg, proto, addr))
+
+
+
+class DatagramProtocolTestCase(unittest.TestCase):
+ """
+ Test various aspects of DNSDatagramProtocol.
+ """
+
+ def testTruncatedPacket(self):
+ """
+ Test that when a short datagram is received, datagramReceived does
+ not raise an exception while processing it.
+ """
+ controller = TestController()
+ proto = dns.DNSDatagramProtocol(controller)
+ proto.datagramReceived('', address.IPv4Address('UDP', '127.0.0.1', 12345))
+ self.assertEquals(controller.messages, [])
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/test/test_names.py new/TwistedNames-0.4.0/twisted/names/test/test_names.py
--- old/TwistedNames-0.3.0/twisted/names/test/test_names.py 2006-04-10 05:21:33.000000000 +0200
+++ new/TwistedNames-0.4.0/twisted/names/test/test_names.py 2006-12-06 04:15:37.000000000 +0100
@@ -12,8 +12,16 @@
from twisted.trial import unittest
from twisted.internet import reactor, defer, error
+from twisted.internet.defer import succeed
from twisted.names import client, server, common, authority, hosts, dns
from twisted.python import failure
+from twisted.names.error import DNSFormatError, DNSServerError, DNSNameError
+from twisted.names.error import DNSNotImplementedError, DNSQueryRefusedError
+from twisted.names.error import DNSUnknownError
+from twisted.names.dns import EFORMAT, ESERVER, ENAME, ENOTIMP, EREFUSED
+from twisted.names.dns import Message
+from twisted.names.client import Resolver
+
def justPayload(results):
return [r.payload for r in results[0]]
@@ -152,8 +160,10 @@
self.resolver = client.Resolver(servers=[('127.0.0.1', port)])
def tearDown(self):
- self.listenerTCP.loseConnection()
- d = defer.maybeDeferred(self.listenerUDP.stopListening)
+ """Asynchronously disconnect listenerTCP, listenerUDP and resolver"""
+ d1 = self.listenerTCP.loseConnection()
+ d2 = defer.maybeDeferred(self.listenerUDP.stopListening)
+ d = defer.gatherResults([d1, d2])
def disconnectTransport(ignored):
if getattr(self.resolver.protocol, 'transport', None) is not None:
return self.resolver.protocol.transport.stopListening()
@@ -557,3 +567,87 @@
r = client.Resolver(resolv=resolvConf)
self.assertEquals(r.dynServers, [('127.0.0.1', 53)])
r._parseCall.cancel()
+
+
+
+class FilterAnswersTests(unittest.TestCase):
+ """
+ Test L{twisted.names.client.Resolver.filterAnswers}'s handling of various
+ error conditions it might encounter.
+ """
+ def setUp(self):
+ # Create a resolver pointed at an invalid server - we won't be hitting
+ # the network in any of these tests.
+ self.resolver = Resolver(servers=[('0.0.0.0', 0)])
+
+
+ def test_truncatedMessage(self):
+ """
+ Test that a truncated message results in an equivalent request made via
+ TCP.
+ """
+ m = Message(trunc=True)
+ m.addQuery('example.com')
+
+ def queryTCP(queries):
+ self.assertEqual(queries, m.queries)
+ response = Message()
+ response.answers = ['answer']
+ response.authority = ['authority']
+ response.additional = ['additional']
+ return succeed(response)
+ self.resolver.queryTCP = queryTCP
+ d = self.resolver.filterAnswers(m)
+ d.addCallback(
+ self.assertEqual, (['answer'], ['authority'], ['additional']))
+ return d
+
+
+ def _rcodeTest(self, rcode, exc):
+ m = Message(rCode=rcode)
+ err = self.resolver.filterAnswers(m)
+ err.trap(exc)
+
+
+ def test_formatError(self):
+ """
+ Test that a message with a result code of C{EFORMAT} results in a
+ failure wrapped around L{DNSFormatError}.
+ """
+ return self._rcodeTest(EFORMAT, DNSFormatError)
+
+
+ def test_serverError(self):
+ """
+ Like L{test_formatError} but for C{ESERVER}/L{DNSServerError}.
+ """
+ return self._rcodeTest(ESERVER, DNSServerError)
+
+
+ def test_nameError(self):
+ """
+ Like L{test_formatError} but for C{ENAME}/L{DNSNameError}.
+ """
+ return self._rcodeTest(ENAME, DNSNameError)
+
+
+ def test_notImplementedError(self):
+ """
+ Like L{test_formatError} but for C{ENOTIMP}/L{DNSNotImplementedError}.
+ """
+ return self._rcodeTest(ENOTIMP, DNSNotImplementedError)
+
+
+ def test_refusedError(self):
+ """
+ Like L{test_formatError} but for C{EREFUSED}/L{DNSQueryRefusedError}.
+ """
+ return self._rcodeTest(EREFUSED, DNSQueryRefusedError)
+
+
+ def test_refusedError(self):
+ """
+ Like L{test_formatError} but for an unrecognized error code and
+ L{DNSUnknownError}.
+ """
+ return self._rcodeTest(EREFUSED + 1, DNSUnknownError)
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/TwistedNames-0.3.0/twisted/names/_version.py new/TwistedNames-0.4.0/twisted/names/_version.py
--- old/TwistedNames-0.3.0/twisted/names/_version.py 2006-05-22 00:28:51.000000000 +0200
+++ new/TwistedNames-0.4.0/twisted/names/_version.py 2007-01-06 22:42:54.000000000 +0100
@@ -1,3 +1,3 @@
# This is an auto-generated file. Use admin/change-versions to update.
from twisted.python import versions
-version = versions.Version(__name__[:__name__.rfind('.')], 0, 3, 0)
+version = versions.Version(__name__[:__name__.rfind('.')], 0, 4, 0)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
---------------------------------------------------------------------
To unsubscribe, e-mail: opensuse-commit+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: opensuse-commit+help@xxxxxxxxxxxx
| < Previous | Next > |