I am working on an embedded system that uses GO v1.13 on the build server. My goal is to make a CANbus manager using linux's socketCAN. Go has a can-go package that is perfect for this solution. However, the package uses the "golang.org/x/sys/" package that uses the unsafe.Slice that was added in Go v1.17. I am unable to upgrade my version to a supported go version.
To solve this issue, I am making my own package that is very similar to can-go but uses syscall.socket instead of unix.socket.
The issue that I have ran into is with the implementation of syscall.Sockaddr. I have implemented it identically to the can-go package but I am getting the following terminal output.
.\canSocket.go:91:42: cannot use &SockaddrCAN literal (type *SockaddrCAN) as type syscall.Sockaddr in argument to syscall.Bind:
*SockaddrCAN does not implement syscall.Sockaddr (missing syscall.sockaddr method)
have sockaddr() (unsafe.Pointer, int32, error)
want syscall.sockaddr() (unsafe.Pointer, int32, error)
I must be missing something very obvious as this looks to be the standard "you are incorrectly implementing an interface" message. I am very new to GO and am expecting that I have missed something fundamental. Can anyone see what I did wrong? Below is the relevant section of my code.
func DialRaw(device string) (net.Conn, error) {
var err error
defer func() {
if err != nil {
err = &net.OpError{Op: "dial", Net: canRawNetwork, Addr: &canRawAddr{device: device}, Err: err}
}
}()
ifi, err := net.InterfaceByName(device)
if err != nil {
return nil, fmt.Errorf("interface %s: %w", device, err)
}
fd, err := syscall.Socket(AF_CAN, SOCK_RAW, CAN_RAW)
if err != nil {
return nil, fmt.Errorf("socket: %w", err)
}
// put fd in non-blocking mode so the created file will be registered by the runtime poller (Go >= 1.12)
if err := syscall.SetNonblock(fd, true); err != nil {
return nil, fmt.Errorf("set nonblock: %w", err)
}
if err := syscall.Bind(fd, &SockaddrCAN{Ifindex: ifi.Index}); err != nil {
return nil, fmt.Errorf("bind: %w", err)
}
return &fileConn{ra: &canRawAddr{device: device}, f: os.NewFile(uintptr(fd), "can")}, nil
}
type RawSockaddrCAN struct {
Family uint16
Ifindex int32
Addr [16]byte
}
type SockaddrCAN struct {
Ifindex int
RxID uint32
TxID uint32
raw RawSockaddrCAN
}
func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, int32, error) {
if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
return nil, 0, EINVAL
}
sa.raw.Family = AF_CAN
sa.raw.Ifindex = int32(sa.Ifindex)
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
for i := 0; i < 4; i++ {
sa.raw.Addr[i] = rx[i]
}
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
for i := 0; i < 4; i++ {
sa.raw.Addr[i+4] = tx[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
}