Brief intro
Hello.
I'm working on VmWare vSockets / VMCI library port from C to Go.
vSockets (previously known as VMCI) are vendor-specific sockets (similar to vsock in Linux) that allow hypervisor and guest communication.
On host side, these sockets behave like regular sockets. The only difference is different socket family number and special sockaddr structure.
socket(), accept() and other methods behave the same.
The problem
I tried to utilize standard methods from syscall package like syscall.Bind and syscall.Accept which behave like eponymous methods from libc but have some extra glue code.
The simplest solution was to import vmci_sockets.h header use cgo but I remember how cgo painful was from previous experience with it, so I decided to move a Go way.
I considered syscall package as the closest low-level alternative to socket-related functions from libc but stumbled upon some limitations.
syscall.Bind
The syscall.Bind method accepts an abstract sockaddr interface which should implement a private Sockaddr.sockaddr method to return raw pointer to a struct and struct size.
As Sockaddr.sockaddr interface cannot be implemented outside of syscall package, currently it's impossible to use this function for vendor-specific sockets.
I believe that this is an artificial constraint because I was able to use an inner private syscall.bind method with some hacks for vSockets socket:
//go:linkname syscallBind syscall.bind
func syscallBind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error)
afVmci, _ := VMCISock_GetAFValue()
sockFd, _ := syscall.Socket(afVmci, syscall.SOCK_STREAM, 0)
addr := newSockAddr(saFamily(afVmci), uint32(port), VMAddrCIDAny)
addrPtr, ptrSize := addr.sockaddr()
// call to unexported private func
if err := syscallBind(sockFd, addrPtr, ptrSize); err != nil {
panic(err)
}
if err := syscall.Listen(sockFd, listenBacklogSize); err != nil {
panic(err)
}
syscall.Accept
Unlike the previous method, syscall.Accept method is more close and only accepts a single parameter - socket file descriptor.
That means, it's impossible to use it for custom sockets (unlike accept() function from libc`)
I tried to take a look how it's implemented in net package and seems like the package uses internal/poll/FD.Accept structure method.
Proposed Actions
I kindly ask the Go contributors and Go team to review my proposal or consider (or recommend) a better solution.
Solution 1
- Make
syscall.Sockaddr.sockaddr method public to make possible implementing it for different sockets.
- Add alternative
syscall.Accept-like method that also accepts custom sockaddr struct (something like FD.accept described above).
Solution 2
Extend net package to make it able to work with custom sockets.
Currently all low-level socket operations are bound to a poll.FD god object-like structure
Thank you.
Brief intro
Hello.
I'm working on VmWare vSockets / VMCI library port from C to Go.
vSockets (previously known as VMCI) are vendor-specific sockets (similar to
vsockin Linux) that allow hypervisor and guest communication.On host side, these sockets behave like regular sockets. The only difference is different socket family number and special
sockaddrstructure.socket(),accept()and other methods behave the same.The problem
I tried to utilize standard methods from
syscallpackage likesyscall.Bindandsyscall.Acceptwhich behave like eponymous methods from libc but have some extra glue code.The simplest solution was to import
vmci_sockets.hheader use cgo but I remember how cgo painful was from previous experience with it, so I decided to move a Go way.I considered
syscallpackage as the closest low-level alternative to socket-related functions from libc but stumbled upon some limitations.syscall.BindThe
syscall.Bindmethod accepts an abstract sockaddr interface which should implement a privateSockaddr.sockaddrmethod to return raw pointer to a struct and struct size.As
Sockaddr.sockaddrinterface cannot be implemented outside ofsyscallpackage, currently it's impossible to use this function for vendor-specific sockets.I believe that this is an artificial constraint because I was able to use an inner private
syscall.bindmethod with some hacks for vSockets socket:syscall.AcceptUnlike the previous method,
syscall.Acceptmethod is more close and only accepts a single parameter - socket file descriptor.That means, it's impossible to use it for custom sockets (unlike
accept()function from libc`)I tried to take a look how it's implemented in
netpackage and seems like the package usesinternal/poll/FD.Acceptstructure method.Proposed Actions
I kindly ask the Go contributors and Go team to review my proposal or consider (or recommend) a better solution.
Solution 1
syscall.Sockaddr.sockaddrmethod public to make possible implementing it for different sockets.syscall.Accept-like method that also accepts custom sockaddr struct (something likeFD.acceptdescribed above).Solution 2
Extend
netpackage to make it able to work with custom sockets.Currently all low-level socket operations are bound to a
poll.FDgod object-like structureThank you.