return cls(socket.ntohs(struct.sin_port), socket.ntohl(struct.sin_addr.s_addr)) @classmethod def sizeof(cls) -> int: return ffi.sizeof('struct sockaddr_in') def addr_as_string(self) -> str: "Returns the addr portion of this address in 127.0.0.1 form" return str(self.addr) def __str__(self) -> str: return f"SockaddrIn({self.addr_as_string()}:{self.port})" _register_sockaddr(SockaddrIn) class SockaddrIn6(Address): "Representation of struct sockaddr_in6" family = AF.INET6 def __init__(self, port: int, addr: t.Union[str, int, ipaddress.IPv6Address], flowinfo: int = 0, scope_id: int = 0) -> None: # these are in host byte order, of course self.port = port self.addr = ipaddress.IPv6Address(addr) self.flowinfo = flowinfo
def to_bytes(self) -> bytes: addr = ffi.new('struct sockaddr_un*', (AF.UNIX, self.path)) real_length = ffi.sizeof('sa_family_t') + len(self.path) + 1 return bytes(ffi.buffer(addr))[:real_length] @classmethod def sizeof(cls) -> int: return ffi.sizeof('struct sockaddr_un') def __str__(self) -> str: return f"SockaddrUn({self.path})" async def close(self) -> None: pass _register_sockaddr(SockaddrUn) class SockaddrUnProcFd(SockaddrUn): def __init__(self, fd: FileDescriptor, name: str) -> None: super().__init__(os.fsencode(f"/proc/self/fd/{int(fd.near)}/{name}")) self.fd = fd self.name = name async def close(self) -> None: await self.fd.close() #### Tests #### from unittest import TestCase class TestUn(TestCase): def test_sockaddrun(self) -> None:
@dataclass class SockaddrNl(Address): # not an actual process pid, but rather "port id", which is unique per netlink socket pid: int groups: int family = AF.NETLINK def to_bytes(self) -> bytes: struct = ffi.new('struct sockaddr_nl*', (AF.NETLINK, 0, self.pid, self.groups)) return bytes(ffi.buffer(struct)) T = t.TypeVar('T', bound='SockaddrNl') @classmethod def from_bytes(cls: t.Type[T], data: bytes) -> T: if len(data) < cls.sizeof(): raise Exception("data too small", data) struct = ffi.cast('struct sockaddr_nl*', ffi.from_buffer(data)) cls.check_family(AF(struct.nl_family)) return cls(struct.nl_pid, struct.nl_groups) @classmethod def sizeof(cls) -> int: return ffi.sizeof('struct sockaddr_nl') _register_sockaddr(SockaddrNl)