''' Demonstrate an actor tree which talks over unix-domain-socket (UDS) transport instead of the default TCP: pass `enable_transports=['uds']` when opening the root and every subactor inherits the preference. Every channel address is a filesystem socket path (no TCP port in sight!) and, as a kernel-provided bonus, the peer's pid is exchanged for free via `SO_PEERCRED`. ''' import os import trio import tractor async def report_addr() -> str: ''' Return this actor's own accept (bind) addr + pid. ''' actor = tractor.current_actor() addr: tuple = actor.accept_addr pid: int = os.getpid() return f'{actor.name}@{addr} pid={pid}' async def main() -> None: async with tractor.open_nursery( enable_transports=['uds'], ) as an: portal = await an.start_actor( 'uds_child', enable_modules=[__name__], ) # the channel's remote addr is a `UDSAddress`: a # filesystem socket path, NOT a (host, port) pair! raddr = portal.chan.raddr assert raddr.proto_key == 'uds' # NOTE, `.sockpath` is the *shared listener* socket file # (named for the root registrar) this channel rode in # on, NOT a per-child path; the child-specific identity # we get for free is the kernel-reported peer pid (via # `SO_PEERCRED`). print( f'portal chan tpt proto: {raddr.proto_key!r}\n' f'listener sock file: {raddr.sockpath}\n' f'kernel-reported peer pid: {raddr.maybe_pid}\n' ) # ask the child for its OWN distinct bind addr: another # socket-file path under the runtime dir. print(f'child says: {await portal.run(report_addr)}') await portal.cancel_actor() if __name__ == '__main__': trio.run(main)