id	summary	reporter	owner	description	type	status	priority	milestone	component	resolution	keywords	cc	branch	branch_author	launchpad_bug
4362	Introduce a new resolver interface (for use by the reactor) which supports multiple addresses and multiple address families	exarkun		"The current resolver interface, `IResolverSimple.getHostByName`, is modeled on `gethostbyname(3)` and inherits the limitations of that API:

  * Only one address can be returned
  * The desired address family cannot be specified

`IResolverSimple` tries to account for the latter by indicating that IPv6 addresses will be returned in preference to IPv4 addresses, but this leads to bugs such as #4212, since the reactor can't actually do anything with an IPv6 address.

`getaddrinfo(3)` was introduced to address the shortcomings of `gethostbyname(3)`.  It allows multiple addresses to be returned, and includes information about the address family of each (although this may be redundant with the address itself, since an ipv4 literal and an ipv6 literal can be distinguished from each other anyway).

It also mixes in `getservbyname(3)` functionality, accepting a service name and including a port number as an attribute of each element in the result.

We should introduce an interface like `getaddrinfo(3)` and switch the reactor to prefer it.  We can register an adapter from the old interface to continue to support users of it.  The new interface will eventually provide better IPv6 functionality, though, and if used will avoid issues like #4212.

Here's a proposal for the actual interface:

{{{
class INameResolver(Interface):
    def getAddressInformation(name, service, family=None, socktype=None, proto=None, flags=None):
        """"""
        Look up the address information associated with the given name.

        @param name: A hostname to resolve.
        @type name: C{str}

        @param service: A port number or the name of the service for which to find address
            information.  For example, C{22} or C{""ssh""}.
        @type service: C{int} or C{str}

        @param family: If specified, limit results to addresses from this family.  Must be one
            of the address family constants from the socket module.  For example,
            L{socket.AF_INET}.

        @param socktype: If specified, limit results to addresses for this socket type.  Must be
            one of the socket type constants from the socket module.  For example,
            L{socket.SOCK_STREAM}.

        @param proto: If specified, limit results to addresses for this socket protocol.  Must
            be one of the protocol constants from the socket module.  For example,
            L{socket.IPPROTO_TCP}.

        @param flags: A bitvector specifying zero or more of the following::

            - Yea right.  Go read the `getaddrinfo(3)` man page.

        @raise ValueError: If one of the specified flags is not supported by the
            implementation.  All flags are optional.

        @return: A L{Deferred} which will fire when the resolution completes.  If resolution is
            successful, the result will be a list of objects with the following attributes:

            - C{family}: the family of this address
            - C{type}: the type of this address
            - C{protocol}: the protocol of this address
            - C{canonicalName}: the canonical name associated with this address, or an empty
                                string.
            - C{address}: The actual address itself, including a port number.  This is suitable
                          to be passed directly to L{socket.socket.connect}.
        """"""
"	enhancement	new	normal		core		ipv6	jknight tom.most@…	branches/getaddrinfo-4362-2	exarkun, rwall	
