qmsk/net/transport/endpoint.py
author Tero Marttila <terom@fixme.fi>
Sun, 23 Aug 2009 23:12:29 +0300
changeset 38 f0fc793a3754
parent 37 14db3fe42b6c
child 44 01ac7755b15a
permissions -rw-r--r--
reorganize transport.endpoint

from qmsk.net.socket import address, constants, af_unix

class AddrInfo (address.addrinfo) :
    """
        Represents a sockaddr along with related address-family etc. information
    """

class Endpoint (object) :
    """
        Abstract network address interface. This can map to multiple actual addresses, potentially of different
        address families.
    """

    def resolve (self, socktype, protocol = 0, passive = True) :
        """
            Translate this Endpoint into a sequence of AddrInfo objects for the given socktype.
        """
        
        raise NotImplemented()

class InetEndpoint (Endpoint) :
    """
        An internet endpoint, supports IPv4, IPv6 addresses and DNS hostnames.

           hostname     - [str] literal address or DNS hostname
           service      - [str] port number or service name
           family       - AF_* associated with this address
    """

    def __init__ (self, hostname=None, service=None, family=constants.AF_UNSPEC) :
        """
            Initialize with given parameters, but doesn't perform any lookups yet.
        """

        self.endpoint = address.endpoint(hostname, service)
        self.family = family
    
    @property
    def hostname (self) :
        return self.endpoint.hostname

    @property
    def service (self) :
        return self.endpoint.service

    def resolve (self, socktype, protocol = 0, passive = True) :
        """
            Resolve using getaddrinfo
        """

        flags = 0

        if passive :
            flags |= constants.AI_PASSIVE

        return self.endpoint.getaddrinfo(self.family, socktype, protocol, flags)

class Address (Endpoint) :
    """
        A specific socket-level address of some address family, also useable as an Endpoint.

            addr        - low-level sockaddr object
            family      - AF_*
    """

    def __init__ (self, sockaddr, family = constants.AF_UNSPEC, canonical = None) :
        if not family :
            family = sockaddr.family

        if not canonical :
            # XXX: delay?
            canonical = str(sockaddr)

        self._sockaddr = sockaddr
        self.family = family
        self.canonical = canonical
    
    def sockaddr (self) :
        """
            Returns a qmsk.net.socket.address.sockaddr object for this address.
        """

        return self._sockaddr

    def resolve (self, socktype, protocol = 0, passive = True) :
        """
            Returns a single AddrInfo object representing this address 
        """
    
        if not socktype :
            raise ValueError("Socket type unknown")

        return [AddrInfo(0, self.family, socktype, protocol, self._sockaddr, self.canonical)]

class InetAddr (Address) :
    """
        An AF_INET/AF_INET6 address, with addr and port.
    """
    
    @property
    def addr (self) :
        return self._sockaddr.addr

    @property
    def port (self) :
        return self._sockaddr.port

class IPv4Addr (InetAddr) :
    """
        A fixed AF_INET address and port
    """

    def __init__ (self, addr, port) :
        super(IPv4Addr, self).__init__(af_inet.sockaddr_in(addr, port))

class IPv6Addr (InetAddr) :
    """
        A fixed AF_INET6 address and port
    """

    def __init__ (self, addr, port) :
        super(IPv6Addr, self).__init__(af_inet6.sockaddr_in6(addr, port))

class UnixAddr (Address) :
    """
        A local AF_UNIX address, as a path.
    """

    def __init__ (self, path) :
        super(UnixAddr, self).__init__(af_unix.sockaddr_un(path))