import time

from diesel import UDPClient, call, send, first, datagram

from dns.message import make_query, from_wire
from dns.rdatatype import A
from dns.resolver import Resolver as ResolvConf


class NotFound(Exception):
    pass

class Timeout(Exception):
    pass

_resolv_conf = ResolvConf()
_local_nameservers = _resolv_conf.nameservers
del _resolv_conf

class DNSClient(UDPClient):
    """A DNS client.

    Uses nameservers from /etc/resolv.conf if none are supplied.

    """
    def __init__(self, servers=None, port=53):
        if servers is None:
            self.nameservers = servers = _local_nameservers
            self.primary = self.nameservers[0]
        super(DNSClient, self).__init__(servers[0], port)

    @call
    def resolve(self, name, timeout=5):
        """Try to resolve name.

        Returns:
            A list of IP addresses for name.

        Raises:
            * Timeout if the request to all servers times out.
            * NotFound if we get a response from a server but the name
              was not resolved.
        
        """
        timeout = timeout / float(len(self.nameservers))
        try:
            for server in self.nameservers:
                # Try each nameserver in succession.
                self.addr = server
                query = make_query(name, A)
                send(query.to_wire())
                start = time.time()
                remaining = timeout
                while True:
                    # Handle the possibility of responses that are not to our
                    # original request - they are ignored and we wait for a
                    # response that matches our query.
                    item, data = first(datagram=True, sleep=remaining)
                    if item == 'datagram':
                        response = from_wire(data)
                        if query.is_response(response):
                            if response.answer:
                                a_records = [r for r in response.answer if r.rdtype == A]
                                return [item.address for item in a_records[0].items]
                            raise NotFound
                        else:
                            # Not a response to our query - continue waiting for
                            # one that is.
                            remaining = remaining - (time.time() - start)
                    elif item == 'sleep':
                        break
            else:
                raise Timeout(name)
        finally:
            self.addr = self.primary


@@ -4,16 +4,46 @@
 ort time
+%0Afrom collections import deque
 %0A%0Afrom d
@@ -366,16 +366,192 @@
 servers%0A
+_search_domains = %5B%5D%0Aif _resolv_conf.domain:%0A    _search_domains.append(str(_resolv_conf.domain)%5B:-1%5D)%0A_search_domains.extend(map(lambda n: str(n)%5B:-1%5D, _resolv_conf.search))%0A%0A
 del _res
@@ -963,16 +963,21 @@
 , name, 
+orig_
 timeout=
@@ -1258,24 +1258,16 @@
 solved.%0A
-        
 %0A       
@@ -1267,24 +1267,627 @@
         %22%22%22%0A
+        names = deque(%5Bname%5D)%0A        for n in _search_domains:%0A            names.append(('%25s.%25s' %25 (name, n)))%0A        start = time.time()%0A        timeout = orig_timeout%0A        r = None%0A        while names:%0A            n = names.popleft()%0A            try:%0A                r = self._actually_resolve(n, timeout)%0A            except:%0A                timeout = orig_timeout - (time.time() - start)%0A                if timeout %3C= 0 or not names:%0A                    raise%0A            else:%0A                break%0A        assert r is not None%0A        return r%0A%0A    def _actually_resolve(self, name, timeout):%0A
         time

Support "domain" and "search".