~ubuntu-branches/ubuntu/feisty/twisted-names/feisty

« back to all changes in this revision

Viewing changes to twisted/names/client.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-17 15:40:25 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070117154025-etmzllar3xw8ecaj
Tags: 0.4.0-0ubuntu1
* New upstream version.
* debian/control: Update (build-)dependencies.
* debian/watch: Update.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- test-case-name: twisted.names.test.test_names -*-
2
 
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 
2
# Copyright (c) 2001-2006 Twisted Matrix Laboratories.
3
3
# See LICENSE for details.
4
4
 
5
5
 
8
8
 
9
9
API Stability: Unstable
10
10
 
 
11
The functions exposed in this module can be used for asynchronous name
 
12
resolution and dns queries.
 
13
 
 
14
If you need to create a resolver with specific requirements, such as needing to
 
15
do queries against a particular host, the L{createResolver} function will
 
16
return an C{IResolver}.
 
17
 
11
18
Future plans: Proper nameserver acquisition on Windows/MacOS,
12
19
better caching, respect timeouts
13
20
 
19
26
import os
20
27
import errno
21
28
 
 
29
from zope.interface import implements
 
30
 
22
31
# Twisted imports
23
32
from twisted.python.runtime import platform
24
33
from twisted.internet import error, defer, protocol, interfaces
25
 
from twisted.python import log, failure, components
26
 
from twisted.names import dns
27
 
from zope.interface import implements
28
 
import common
 
34
from twisted.python import log, failure
 
35
from twisted.names import dns, common
 
36
from twisted.names.error import DNSFormatError, DNSServerError, DNSNameError
 
37
from twisted.names.error import DNSNotImplementedError, DNSQueryRefusedError
 
38
from twisted.names.error import DNSUnknownError
 
39
 
29
40
 
30
41
class Resolver(common.ResolverBase):
31
42
    implements(interfaces.IResolver)
44
55
    _lastResolvTime = None
45
56
    _resolvReadInterval = 60
46
57
 
 
58
    _errormap = {
 
59
        dns.EFORMAT: DNSFormatError,
 
60
        dns.ESERVER: DNSServerError,
 
61
        dns.ENAME: DNSNameError,
 
62
        dns.ENOTIMP: DNSNotImplementedError,
 
63
        dns.EREFUSED: DNSQueryRefusedError}
 
64
 
47
65
    def __init__(self, resolv = None, servers = None, timeout = (1, 3, 11, 45)):
48
66
        """
49
67
        Construct a resolver which will query domain name servers listed in
53
71
        for modification and re-parsed if it is noticed to have changed.
54
72
 
55
73
        @type servers: C{list} of C{(str, int)} or C{None}
56
 
        @param servers: If not None, interpreted as a list of addresses of
 
74
        @param servers: If not C{None}, interpreted as a list of addresses of
57
75
        domain name servers to attempt to use for this lookup.  Addresses
58
76
        should be in dotted-quad form.  If specified, overrides C{resolv}.
59
77
 
271
289
 
272
290
 
273
291
    def filterAnswers(self, message):
 
292
        """
 
293
        Extract results from the given message.
 
294
 
 
295
        If the message was truncated, re-attempt the query over TCP and return
 
296
        a Deferred which will fire with the results of that query.
 
297
 
 
298
        If the message's result code is not L{dns.OK}, return a Failure
 
299
        indicating the type of error which occurred.
 
300
 
 
301
        Otherwise, return a three-tuple of lists containing the results from
 
302
        the answers section, the authority section, and the additional section.
 
303
        """
274
304
        if message.trunc:
275
305
            return self.queryTCP(message.queries).addCallback(self.filterAnswers)
276
 
        else:
277
 
            return (message.answers, message.authority, message.additional)
 
306
        if message.rCode != dns.OK:
 
307
            return failure.Failure(self._errormap.get(message.rCode, DNSUnknownError)(message))
 
308
        return (message.answers, message.authority, message.additional)
278
309
 
279
310
 
280
311
    def _lookup(self, name, cls, type, timeout):
385
416
 
386
417
 
387
418
 
388
 
def createResolver(servers = None, resolvconf = None, hosts = None):
 
419
def createResolver(servers=None, resolvconf=None, hosts=None):
 
420
    """
 
421
    Create and return a Resolver.
 
422
 
 
423
    @type servers: C{list} of C{(str, int)} or C{None}
 
424
    @param servers: If not C{None}, interpreted as a list of addresses of
 
425
    domain name servers to attempt to use.  Addresses should be in dotted-quad
 
426
    form.
 
427
 
 
428
    @type resolvconf: C{str} or C{None}
 
429
    @param resolvconf: If not C{None}, on posix systems will be interpreted as
 
430
    an alternate resolv.conf to use. Will do nothing on windows systems. If
 
431
    C{None}, /etc/resolv.conf will be used.
 
432
 
 
433
    @type hosts: C{str} or C{None}
 
434
    @param hosts: If not C{None}, an alternate hosts file to use. If C{None}
 
435
    on posix systems, /etc/hosts will be used. On windows, C:\windows\hosts
 
436
    will be used.
 
437
 
 
438
    @rtype: C{IResolver}
 
439
    """
389
440
    from twisted.names import resolve, cache, root, hosts as hostsModule
390
441
    if platform.getType() == 'posix':
391
442
        if resolvconf is None:
406
457
    return resolve.ResolverChain(L)
407
458
 
408
459
theResolver = None
409
 
def _makeLookup(method):
410
 
    def lookup(*a, **kw):
411
 
        global theResolver
412
 
        if theResolver is None:
413
 
            try:
414
 
                theResolver = createResolver()
415
 
            except ValueError:
416
 
                theResolver = createResolver(servers=[('127.0.0.1', 53)])
417
 
 
418
 
        return getattr(theResolver, method)(*a, **kw)
419
 
    return lookup
420
 
 
421
 
for method in common.typeToMethod.values():
422
 
    globals()[method] = _makeLookup(method)
423
 
del method
424
 
 
425
 
getHostByName = _makeLookup('getHostByName')
 
460
def getResolver():
 
461
    """
 
462
    Get a Resolver instance.
 
463
 
 
464
    Create twisted.names.client.theResolver if it is C{None}, and then return
 
465
    that value.
 
466
 
 
467
    @rtype: C{IResolver}
 
468
    """
 
469
    global theResolver
 
470
    if theResolver is None:
 
471
        try:
 
472
            theResolver = createResolver()
 
473
        except ValueError:
 
474
            theResolver = createResolver(servers=[('127.0.0.1', 53)])
 
475
    return theResolver
 
476
 
 
477
def getHostByName(name, timeout=None, effort=10):
 
478
    """
 
479
    Resolve a name to a valid ipv4 or ipv6 address.
 
480
 
 
481
    Will errback with C{DNSQueryTimeoutError} on a timeout, C{DomainError} or
 
482
    C{AuthoritativeDomainError} (or subclasses) on other errors.
 
483
 
 
484
    @type name: C{str}
 
485
    @param name: DNS name to resolve.
 
486
 
 
487
    @type timeout: Sequence of C{int}
 
488
    @param timeout: Number of seconds after which to reissue the query.
 
489
    When the last timeout expires, the query is considered failed.
 
490
 
 
491
    @type effort: C{int}
 
492
    @param effort: How many times CNAME and NS records to follow while
 
493
    resolving this name.
 
494
 
 
495
    @rtype: C{Deferred}
 
496
    """
 
497
    return getResolver().getHostByName(name, timeout, effort)
 
498
 
 
499
def lookupAddress(name, timeout=None):
 
500
    """
 
501
    Perform an A record lookup.
 
502
 
 
503
    @type name: C{str}
 
504
    @param name: DNS name to resolve.
 
505
    
 
506
    @type timeout: Sequence of C{int}
 
507
    @param timeout: Number of seconds after which to reissue the query.
 
508
    When the last timeout expires, the query is considered failed.
 
509
    
 
510
    @rtype: C{Deferred}
 
511
    """
 
512
    return getResolver().lookupAddress(name, timeout)
 
513
 
 
514
def lookupIPV6Address(name, timeout=None):
 
515
    """
 
516
    Perform an AAAA record lookup.
 
517
 
 
518
    @type name: C{str}
 
519
    @param name: DNS name to resolve.
 
520
    
 
521
    @type timeout: Sequence of C{int}
 
522
    @param timeout: Number of seconds after which to reissue the query.
 
523
    When the last timeout expires, the query is considered failed.
 
524
    
 
525
    @rtype: C{Deferred}
 
526
    """
 
527
    return getResolver().lookupIPV6Address(name, timeout)
 
528
 
 
529
def lookupAddress6(name, timeout=None):
 
530
    """
 
531
    Perform an A6 record lookup.
 
532
 
 
533
    @type name: C{str}
 
534
    @param name: DNS name to resolve.
 
535
    
 
536
    @type timeout: Sequence of C{int}
 
537
    @param timeout: Number of seconds after which to reissue the query.
 
538
    When the last timeout expires, the query is considered failed.
 
539
    
 
540
    @rtype: C{Deferred}
 
541
    """
 
542
    return getResolver().lookupAddress6(name, timeout)
 
543
 
 
544
def lookupMailExchange(name, timeout=None):
 
545
    """
 
546
    Perform an MX record lookup.
 
547
 
 
548
    @type name: C{str}
 
549
    @param name: DNS name to resolve.
 
550
    
 
551
    @type timeout: Sequence of C{int}
 
552
    @param timeout: Number of seconds after which to reissue the query.
 
553
    When the last timeout expires, the query is considered failed.
 
554
    
 
555
    @rtype: C{Deferred}
 
556
    """
 
557
    return getResolver().lookupMailExchange(name, timeout)
 
558
 
 
559
def lookupNameservers(name, timeout=None):
 
560
    """
 
561
    Perform an NS record lookup.
 
562
 
 
563
    @type name: C{str}
 
564
    @param name: DNS name to resolve.
 
565
    
 
566
    @type timeout: Sequence of C{int}
 
567
    @param timeout: Number of seconds after which to reissue the query.
 
568
    When the last timeout expires, the query is considered failed.
 
569
    
 
570
    @rtype: C{Deferred}
 
571
    """
 
572
    return getResolver().lookupNameservers(name, timeout)
 
573
 
 
574
def lookupCanonicalName(name, timeout=None):
 
575
    """
 
576
    Perform a CNAME record lookup.
 
577
 
 
578
    @type name: C{str}
 
579
    @param name: DNS name to resolve.
 
580
    
 
581
    @type timeout: Sequence of C{int}
 
582
    @param timeout: Number of seconds after which to reissue the query.
 
583
    When the last timeout expires, the query is considered failed.
 
584
    
 
585
    @rtype: C{Deferred}
 
586
    """
 
587
    return getResolver().lookupCanonicalName(name, timeout)
 
588
 
 
589
def lookupMailBox(name, timeout=None):
 
590
    """
 
591
    Perform an MB record lookup.
 
592
 
 
593
    @type name: C{str}
 
594
    @param name: DNS name to resolve.
 
595
    
 
596
    @type timeout: Sequence of C{int}
 
597
    @param timeout: Number of seconds after which to reissue the query.
 
598
    When the last timeout expires, the query is considered failed.
 
599
    
 
600
    @rtype: C{Deferred}
 
601
    """
 
602
    return getResolver().lookupMailBox(name, timeout)
 
603
 
 
604
def lookupMailGroup(name, timeout=None):
 
605
    """
 
606
    Perform an MG record lookup.
 
607
 
 
608
    @type name: C{str}
 
609
    @param name: DNS name to resolve.
 
610
    
 
611
    @type timeout: Sequence of C{int}
 
612
    @param timeout: Number of seconds after which to reissue the query.
 
613
    When the last timeout expires, the query is considered failed.
 
614
    
 
615
    @rtype: C{Deferred}
 
616
    """
 
617
    return getResolver().lookupMailGroup(name, timeout)
 
618
 
 
619
def lookupMailRename(name, timeout=None):
 
620
    """
 
621
    Perform an MR record lookup.
 
622
 
 
623
    @type name: C{str}
 
624
    @param name: DNS name to resolve.
 
625
    
 
626
    @type timeout: Sequence of C{int}
 
627
    @param timeout: Number of seconds after which to reissue the query.
 
628
    When the last timeout expires, the query is considered failed.
 
629
    
 
630
    @rtype: C{Deferred}
 
631
    """
 
632
    return getResolver().lookupMailRename(name, timeout)
 
633
 
 
634
def lookupPointer(name, timeout=None):
 
635
    """
 
636
    Perform a PTR record lookup.
 
637
 
 
638
    @type name: C{str}
 
639
    @param name: DNS name to resolve.
 
640
    
 
641
    @type timeout: Sequence of C{int}
 
642
    @param timeout: Number of seconds after which to reissue the query.
 
643
    When the last timeout expires, the query is considered failed.
 
644
    
 
645
    @rtype: C{Deferred}
 
646
    """
 
647
    return getResolver().lookupPointer(name, timeout)
 
648
 
 
649
def lookupAuthority(name, timeout=None):
 
650
    """
 
651
    Perform an SOA record lookup.
 
652
 
 
653
    @type name: C{str}
 
654
    @param name: DNS name to resolve.
 
655
    
 
656
    @type timeout: Sequence of C{int}
 
657
    @param timeout: Number of seconds after which to reissue the query.
 
658
    When the last timeout expires, the query is considered failed.
 
659
    
 
660
    @rtype: C{Deferred}
 
661
    """
 
662
    return getResolver().lookupAuthority(name, timeout)
 
663
 
 
664
def lookupNull(name, timeout=None):
 
665
    """
 
666
    Perform a NULL record lookup.
 
667
 
 
668
    @type name: C{str}
 
669
    @param name: DNS name to resolve.
 
670
    
 
671
    @type timeout: Sequence of C{int}
 
672
    @param timeout: Number of seconds after which to reissue the query.
 
673
    When the last timeout expires, the query is considered failed.
 
674
    
 
675
    @rtype: C{Deferred}
 
676
    """
 
677
    return getResolver().lookupNull(name, timeout)
 
678
 
 
679
def lookupWellKnownServices(name, timeout=None):
 
680
    """
 
681
    Perform a WKS record lookup.
 
682
 
 
683
    @type name: C{str}
 
684
    @param name: DNS name to resolve.
 
685
    
 
686
    @type timeout: Sequence of C{int}
 
687
    @param timeout: Number of seconds after which to reissue the query.
 
688
    When the last timeout expires, the query is considered failed.
 
689
    
 
690
    @rtype: C{Deferred}
 
691
    """
 
692
    return getResolver().lookupWellKnownServices(name, timeout)
 
693
 
 
694
def lookupService(name, timeout=None):
 
695
    """
 
696
    Perform an SRV record lookup.
 
697
 
 
698
    @type name: C{str}
 
699
    @param name: DNS name to resolve.
 
700
    
 
701
    @type timeout: Sequence of C{int}
 
702
    @param timeout: Number of seconds after which to reissue the query.
 
703
    When the last timeout expires, the query is considered failed.
 
704
    
 
705
    @rtype: C{Deferred}
 
706
    """
 
707
    return getResolver().lookupService(name, timeout)
 
708
 
 
709
def lookupHostInfo(name, timeout=None):
 
710
    """
 
711
    Perform a HINFO record lookup.
 
712
 
 
713
    @type name: C{str}
 
714
    @param name: DNS name to resolve.
 
715
    
 
716
    @type timeout: Sequence of C{int}
 
717
    @param timeout: Number of seconds after which to reissue the query.
 
718
    When the last timeout expires, the query is considered failed.
 
719
    
 
720
    @rtype: C{Deferred}
 
721
    """
 
722
    return getResolver().lookupHostInfo(name, timeout)
 
723
 
 
724
def lookupMailboxInfo(name, timeout=None):
 
725
    """
 
726
    Perform an MINFO record lookup.
 
727
 
 
728
    @type name: C{str}
 
729
    @param name: DNS name to resolve.
 
730
    
 
731
    @type timeout: Sequence of C{int}
 
732
    @param timeout: Number of seconds after which to reissue the query.
 
733
    When the last timeout expires, the query is considered failed.
 
734
    
 
735
    @rtype: C{Deferred}
 
736
    """
 
737
    return getResolver().lookupMailboxInfo(name, timeout)
 
738
 
 
739
def lookupText(name, timeout=None):
 
740
    """
 
741
    Perform a TXT record lookup.
 
742
 
 
743
    @type name: C{str}
 
744
    @param name: DNS name to resolve.
 
745
    
 
746
    @type timeout: Sequence of C{int}
 
747
    @param timeout: Number of seconds after which to reissue the query.
 
748
    When the last timeout expires, the query is considered failed.
 
749
    
 
750
    @rtype: C{Deferred}
 
751
    """
 
752
    return getResolver().lookupText(name, timeout)
 
753
 
 
754
def lookupResponsibility(name, timeout=None):
 
755
    """
 
756
    Perform an RP record lookup.
 
757
 
 
758
    @type name: C{str}
 
759
    @param name: DNS name to resolve.
 
760
    
 
761
    @type timeout: Sequence of C{int}
 
762
    @param timeout: Number of seconds after which to reissue the query.
 
763
    When the last timeout expires, the query is considered failed.
 
764
    
 
765
    @rtype: C{Deferred}
 
766
    """
 
767
    return getResolver().lookupResponsibility(name, timeout)
 
768
 
 
769
def lookupAFSDatabase(name, timeout=None):
 
770
    """
 
771
    Perform an AFSDB record lookup.
 
772
 
 
773
    @type name: C{str}
 
774
    @param name: DNS name to resolve.
 
775
    
 
776
    @type timeout: Sequence of C{int}
 
777
    @param timeout: Number of seconds after which to reissue the query.
 
778
    When the last timeout expires, the query is considered failed.
 
779
    
 
780
    @rtype: C{Deferred}
 
781
    """
 
782
    return getResolver().lookupAFSDatabase(name, timeout)
 
783
 
 
784
def lookupZone(name, timeout=None):
 
785
    """
 
786
    Perform an AXFR record lookup.
 
787
 
 
788
    @type name: C{str}
 
789
    @param name: DNS name to resolve.
 
790
    
 
791
    @type timeout: C{int}
 
792
    @param timeout: When this timeout expires, the query is considered failed.
 
793
    
 
794
    @rtype: C{Deferred}
 
795
    """
 
796
    # XXX: timeout here is not a list of ints, it is a single int.
 
797
    return getResolver().lookupZone(name, timeout)
 
798
 
 
799
def lookupAllRecords(name, timeout=None):
 
800
    """
 
801
    ALL_RECORD lookup.
 
802
 
 
803
    @type name: C{str}
 
804
    @param name: DNS name to resolve.
 
805
    
 
806
    @type timeout: Sequence of C{int}
 
807
    @param timeout: Number of seconds after which to reissue the query.
 
808
    When the last timeout expires, the query is considered failed.
 
809
    
 
810
    @rtype: C{Deferred}
 
811
    """
 
812
    return getResolver().lookupAllRecords(name, timeout)
 
813