client.py :  » Network » Twisted » Twisted-1.0.3 » Twisted-1.0.3 » twisted » names » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Twisted 
Twisted » Twisted 1.0.3 » Twisted 1.0.3 » twisted » names » client.py

# Twisted, the Framework of Your Internet
# Copyright (C) 2001 Matthew W. Lefkowitz
# 
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
# 
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""
Asynchronous client DNS

API Stability: Unstable

Future plans: Proper nameserver acquisition on Windows/MacOS,
better caching, respect timeouts

@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
"""

from __future__ import nested_scopes

import socket

# Twisted imports
from twisted.python.runtime import platform
from twisted.internet import defer,protocol,interfaces,threads
from twisted.python import log
from twisted.protocols import dns

import common


class Resolver(common.ResolverBase):
    __implements__ = (interfaces.IResolver,)

    index = 0
    timeout = 10

    factory = None
    servers = None
    pending = None
    protocol = None
    connections = None

    def __init__(self, resolv = None, servers = None, timeout = 10):
        """
        @type servers: C{list} of C{(str, int)} or C{None}
        @param servers: If not 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}.
        
        @type resolv: C{str}
        @param resolv: Filename to read and parse as a resolver(5)
        configuration file.
        
        @type timeout: C{int}
        @param timeout: Default number of seconds after which to fail with a
        C{twisted.internet.defer.TimeoutError}
        
        @raise ValueError: Raised if no nameserver addresses can be found.
        """
        common.ResolverBase.__init__(self)

        self.timeout = timeout

        if servers is None:
            self.servers = []
        else:
            self.servers = servers
        
        if resolv:
            self.parseConfig(resolv)
        
        if not len(self.servers):
            raise ValueError, "No nameservers specified"
        
        self.factory = DNSClientFactory(self, timeout)
        self.factory.noisy = 0   # Be quiet by default
        
        self.protocol = dns.DNSDatagramProtocol(self)
        self.protocol.noisy = 0  # You too
        
        self.connections = []
        self.pending = []


    def __getstate__(self):
        d = self.__dict__.copy()
        d['connections'] = []
        return d


    def parseConfig(self, conf):
        lines = open(conf).readlines()
        for l in lines:
            l = l.strip()
            if l.startswith('nameserver'):
                self.servers.append((l.split()[1], dns.PORT))
                log.msg("Resolver added %r to server list" % (self.servers[-1],))
            elif l.startswith('domain'):
                self.domain = l.split()[1]
                self.search = None
            elif l.startswith('search'):
                self.search = l.split()[1:]
                self.domain = None


    def pickServer(self):
        """
        Return the address of a nameserver.
        
        TODO: Weight servers for response time so faster ones can be
        preferred.
        """
        self.index = (self.index + 1) % len(self.servers)
        return self.servers[self.index]


    def connectionMade(self, protocol):
        self.connections.append(protocol)
        # XXX - need to use timeout
        for (d, q, t) in self.pending:
            protocol.query(q).chainDeferred(d)
        del self.pending[:]
    
    
    def messageReceived(self, protocol, message, address = None):
        log.msg("Unexpected message received from %r" % (address,))


    def queryUDP(self, queries, timeout = None):
        """
        Make a number of DNS queries via UDP.

        @type queries: A C{list} of C{dns.Query} instances
        @param queries: The queries to make.
        
        @type timeout: C{int}
        @param timeout: Number of seconds after which to give up the query.

        @rtype: C{Deferred}
        @raise C{twisted.internet.defer.TimeoutError}: When the query times
        out.
        """
        address = self.pickServer()
        if timeout is None:
            timeout = self.timeout
        return self.protocol.query(address, queries, timeout)


    def queryTCP(self, queries, timeout = None):
        """
        Make a number of DNS queries via TCP.

        @type queries: Any non-zero number of C{dns.Query} instances
        @param queries: The queries to make.
        
        @rtype: C{Deferred}
        """
        if not len(self.connections):
            host, port = self.pickServer()
            from twisted.internet import reactor
            reactor.connectTCP(host, port, self.factory)
            self.pending.append((defer.Deferred(), queries, timeout))
            return self.pending[-1][0]
        else:
            return self.connections[0].query(queries)


    def filterAnswers(self, message):
        if message.trunc:
            return self.queryTCP(message.queries).addCallback(self.filterAnswers)
        else:
            return (message.answers, message.authority, message.additional)


    def _lookup(self, name, cls, type, timeout):
        return self.queryUDP(
            [dns.Query(name, type, cls)], timeout
        ).addCallback(self.filterAnswers)
    
    
    # This one doesn't ever belong on UDP
    def lookupZone(self, name, timeout = 10):
        return self.queryTCP(
            [dns.Query(name, dns.AXFR, dns.IN)], timeout
        ).addCallback(self.filterAnswers)


class ThreadedResolver:
    __implements__ = (interfaces.IResolverSimple,)

    def __init__(self):
        self.cache = {}

    def getHostByName(self, name, timeout = 10):
        # XXX - Make this respect timeout
        return threads.deferToThread(socket.gethostbyname, name)


class DNSClientFactory(protocol.ClientFactory):
    def __init__(self, controller, timeout = 10):
        self.controller = controller
        self.timeout = timeout
    

    def clientConnectionLost(self, connector, reason):
        pass


    def buildProtocol(self, addr):
        p = dns.DNSProtocol(self.controller)
        p.factory = self
        return p


def createResolver(servers = None):
    import resolve, cache, hosts
    if platform.getType() == 'posix':
        theResolver = Resolver('/etc/resolv.conf', servers)
        hostResolver = hosts.Resolver()
    else:
        theResolver = ThreadedResolver()
        hostResolver = hosts.Resolver(r'c:\windows\hosts')
    return resolve.ResolverChain([hostResolver, cache.CacheResolver(), theResolver])

try:
    theResolver
except NameError:
    try:
        theResolver = createResolver()
    except ValueError:
        theResolver = createResolver(servers=[('127.0.0.1', 53)])

    for (k, v) in common.typeToMethod.items():
        exec "%s = getattr(theResolver, %r)" % (v, v)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.