New I/O: using send/receive with connected sockets

Hi everyone, this is a question on either how to do this, or if this might be supported in the future, if this is not implemented yet. I understand I might be asking for something that is in active development, in which case I’m happy to patiently wait for 0.16.

I’ve been trying to set up a Unix domain socket with std.Io.net. So, it looks like I need to try passing the local socket path to Io.net.UnixAddress, and I get net.Stream from .connect(). So far so good.

Now, it looks like net.Stream has a .reader() and .writer() that I can use to read and write. Reader/Writer is what I would want to use, except I need to use the connection like a socket, mainly also to send and receive control data that comes/goes with SCM_RIGHTS on sendmsg/recvmsg.

Okay, maybe I need to look at the methods in Stream.Socket. These seem to work with IncomingMessage/OutgoingMessage, which have a field for control data. I’m losing the convenient reader/writer, although I’m not sure how those would be structured while also handling the ancillary data.

When I try calling stream.socket.send():

thread 28224 panic: programmer bug caused syscall error: ISCONN

Oh, the Socket methods specifically say connectionless. It seems like they require an address, while with a connected socket it would be passed as null in the msghdr.

So maybe I just need to write my own little wrapper around the Io.VTable. It must be netRead/netWrite and netSend/netReceive that I’ve been calling above. Looking into netSendPosix from Threaded:

        msg.* = .{
            .hdr = .{
                .name = &addr.any,
                .namelen = addressToPosix(message.address, addr),
                .iov = iovec[0..1],
                .iovlen = 1,
                .control = @constCast(message.control.ptr),
                .controllen = message.control.len,
                .flags = 0,
            },
            .len = undefined, // Populated by calling sendmmsg below.
        };

So netSend/netReceive are what I want to be calling because this ends up with a sendmsg call that handles cmsg, but they seem only made for connectionless sockets, always populating .name with the address from Incoming/OutgoingMessage.

So I can’t really write a workaround that is still uses Io, because the interface doesn’t seem to have functions for connected sockets? And that’s where I think I’m probably missing something obvious, or I need to just wait for it to be implemented, because this is still just master branch, so here I am with the lengthy question.

My use case specifically is local servers like Wayland or PipeWire, that do client-host IPC through Unix domain socket and transfer file descriptors with SCM_RIGHTS.

I see #30892 / #30837 after writing all of this which seem to be directly addressing the issue :upside_down_face: