Skip to content

syscall: allow registration of new socket types for package net #15021

Closed
@mdlayher

Description

@mdlayher

Overview

At this time, there is no mechanism for socket types outside of the standard library to access the runtime network poller. This proposal, if accepted, would enable a resolution to issue #10565. This would enable packages outside of the standard library to take advantage of the runtime network poller, instead of implementing their own network polling mechanism.

Proposed Change

I propose adding a new API to package net which enables registration of arbitrary sockets for use with the runtime network poller. The design of this API is based upon a comment from @rsc found here: #11492 (comment).

It seems to me that the net package should just keep using (and providing) only FileConn but perhaps we can put a registration mechanism in package syscall to let clients register converters between sockaddrs and net.Addr for non-standard sockaddr types.

This is what I was able to come up with after a little bit of experimentation. Parameter list is to be determined, but this is what I was able to get working with my prototype on a Linux system. Efforts will be made to make this mechanism as generic and cross-platform friendly as possible, but it may not be implemented immediately on non-UNIX platforms. From what I can tell, syscall.Sockaddr does appear to be available on all platforms.

package net

// Registration mechanism, perhaps called in init() or main() when a
// socket is first initalized.
func RegisterSocket(
    family int,
    sockaddr syscall.Sockaddr,
    addr Addr,
    convertSockaddr func(syscall.Sockaddr) Addr,
    convertNetAddr func(Addr) syscall.Sockaddr,
)

// Generic net.Conn and net.PacketConn implementation which embeds the
// internal net.conn type.  Checks for registered socket hooks to determine
// validity of sent and received net.Addr implementations.
type SocketConn struct {
    conn
}

Example

Using a modified version of package net, I was able to gain access to the runtime network poller and
simplify my raw sockets package code to something like the following:

// Called in init() in package raw
net.RegisterSocket(
    syscall.AF_PACKET,
    &syscall.SockaddrLinklayer{},
    &Addr{},
    // internal conversion functions for syscall.SockaddrLinklayer <-> raw.Addr
    convertSockaddr,
    convertNetAddr,
)

sock, _ := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, proto)
_ = syscall.Bind(sock, &syscall.SockaddrLinklayer{
    Protocol: pbe,
    Ifindex:  ifi.Index,
})
f := os.NewFile(uintptr(sock), "linklayer")
// c is type net.SocketConn, backed by raw socket (uses raw.Addr for addressing)
c := net.FilePacketConn(f)

Summary

The runtime network poller is an excellent mechanism, and enabling access to it will allow the future development of packages for raw ethernet sockets, netlink sockets, and other platform-specific socket types.

If this proposal is accepted, I'd happily seek guidance from @mikioh regarding creating the best possible API for this feature. In addition, this would enable me to contribute code from my raw ethernet socket package as a resolution to #8432.

Questions and comments appreciated, and thanks for your time.

/cc @rsc @mikioh

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions