2019-11-19 18:00:20 +01:00
|
|
|
package nebula
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
"golang.org/x/sys/unix"
|
|
|
|
)
|
|
|
|
|
|
|
|
//TODO: make it support reload as best you can!
|
|
|
|
|
|
|
|
type udpConn struct {
|
|
|
|
sysFd int
|
|
|
|
}
|
|
|
|
|
|
|
|
type udpAddr struct {
|
|
|
|
IP uint32
|
|
|
|
Port uint16
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUDPAddr(ip uint32, port uint16) *udpAddr {
|
|
|
|
return &udpAddr{IP: ip, Port: port}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUDPAddrFromString(s string) *udpAddr {
|
|
|
|
p := strings.Split(s, ":")
|
|
|
|
if len(p) < 2 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
port, _ := strconv.Atoi(p[1])
|
|
|
|
return &udpAddr{
|
|
|
|
IP: ip2int(net.ParseIP(p[0])),
|
|
|
|
Port: uint16(port),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type rawSockaddr struct {
|
|
|
|
Family uint16
|
|
|
|
Data [14]uint8
|
|
|
|
}
|
|
|
|
|
|
|
|
type rawSockaddrAny struct {
|
|
|
|
Addr rawSockaddr
|
|
|
|
Pad [96]int8
|
|
|
|
}
|
|
|
|
|
|
|
|
var x int
|
|
|
|
|
|
|
|
func NewListener(ip string, port int, multi bool) (*udpConn, error) {
|
|
|
|
syscall.ForkLock.RLock()
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
|
2019-11-19 18:00:20 +01:00
|
|
|
if err == nil {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
unix.CloseOnExec(fd)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
syscall.ForkLock.RUnlock()
|
|
|
|
|
|
|
|
if err != nil {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
unix.Close(fd)
|
2019-11-23 00:22:31 +01:00
|
|
|
return nil, fmt.Errorf("unable to open socket: %s", err)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var lip [4]byte
|
|
|
|
copy(lip[:], net.ParseIP(ip).To4())
|
|
|
|
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
|
2019-11-23 00:22:31 +01:00
|
|
|
return nil, fmt.Errorf("unable to set SO_REUSEPORT: %s", err)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2019-12-17 17:46:48 +01:00
|
|
|
if err = unix.Bind(fd, &unix.SockaddrInet4{Addr: lip, Port: port}); err != nil {
|
2019-11-23 00:22:31 +01:00
|
|
|
return nil, fmt.Errorf("unable to bind to socket: %s", err)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: this may be useful for forcing threads into specific cores
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
//unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_INCOMING_CPU, x)
|
|
|
|
//v, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_INCOMING_CPU)
|
2019-11-19 18:00:20 +01:00
|
|
|
//l.Println(v, err)
|
|
|
|
|
|
|
|
return &udpConn{sysFd: fd}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) SetRecvBuffer(n int) error {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, n)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) SetSendBuffer(n int) error {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, n)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) GetRecvBuffer() (int, error) {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_RCVBUF)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) GetSendBuffer() (int, error) {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_SNDBUF)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) LocalAddr() (*udpAddr, error) {
|
|
|
|
var rsa rawSockaddrAny
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
var rLen = unix.SizeofSockaddrAny
|
2019-11-19 18:00:20 +01:00
|
|
|
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
_, _, err := unix.Syscall(
|
|
|
|
unix.SYS_GETSOCKNAME,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
|
|
|
uintptr(unsafe.Pointer(&rsa)),
|
|
|
|
uintptr(unsafe.Pointer(&rLen)),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
addr := &udpAddr{}
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
if rsa.Addr.Family == unix.AF_INET {
|
2019-11-19 18:00:20 +01:00
|
|
|
addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1])
|
|
|
|
addr.IP = uint32(rsa.Addr.Data[2])<<24 + uint32(rsa.Addr.Data[3])<<16 + uint32(rsa.Addr.Data[4])<<8 + uint32(rsa.Addr.Data[5])
|
|
|
|
} else {
|
|
|
|
addr.Port = 0
|
|
|
|
addr.IP = 0
|
|
|
|
}
|
|
|
|
return addr, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) ListenOut(f *Interface) {
|
|
|
|
plaintext := make([]byte, mtu)
|
|
|
|
header := &Header{}
|
|
|
|
fwPacket := &FirewallPacket{}
|
|
|
|
udpAddr := &udpAddr{}
|
|
|
|
nb := make([]byte, 12, 12)
|
|
|
|
|
|
|
|
//TODO: should we track this?
|
|
|
|
//metric := metrics.GetOrRegisterHistogram("test.batch_read", nil, metrics.NewExpDecaySample(1028, 0.015))
|
|
|
|
msgs, buffers, names := u.PrepareRawMessages(f.udpBatchSize)
|
|
|
|
|
|
|
|
for {
|
|
|
|
n, err := u.ReadMulti(msgs)
|
|
|
|
if err != nil {
|
|
|
|
l.WithError(err).Error("Failed to read packets")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
//metric.Update(int64(n))
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
udpAddr.IP = binary.BigEndian.Uint32(names[i][4:8])
|
|
|
|
udpAddr.Port = binary.BigEndian.Uint16(names[i][2:4])
|
|
|
|
|
|
|
|
f.readOutsidePackets(udpAddr, plaintext[:0], buffers[i][:msgs[i].Len], header, fwPacket, nb)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) Read(addr *udpAddr, b []byte) ([]byte, error) {
|
|
|
|
var rsa rawSockaddrAny
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
var rLen = unix.SizeofSockaddrAny
|
2019-11-19 18:00:20 +01:00
|
|
|
|
|
|
|
for {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
n, _, err := unix.Syscall6(
|
|
|
|
unix.SYS_RECVFROM,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
|
|
|
uintptr(unsafe.Pointer(&b[0])),
|
|
|
|
uintptr(len(b)),
|
|
|
|
uintptr(0),
|
|
|
|
uintptr(unsafe.Pointer(&rsa)),
|
|
|
|
uintptr(unsafe.Pointer(&rLen)),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
|
|
|
return nil, &net.OpError{Op: "read", Err: err}
|
|
|
|
}
|
|
|
|
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
if rsa.Addr.Family == unix.AF_INET {
|
2019-11-19 18:00:20 +01:00
|
|
|
addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1])
|
|
|
|
addr.IP = uint32(rsa.Addr.Data[2])<<24 + uint32(rsa.Addr.Data[3])<<16 + uint32(rsa.Addr.Data[4])<<8 + uint32(rsa.Addr.Data[5])
|
|
|
|
} else {
|
|
|
|
addr.Port = 0
|
|
|
|
addr.IP = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
return b[:n], nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) ReadMulti(msgs []rawMessage) (int, error) {
|
|
|
|
for {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
n, _, err := unix.Syscall6(
|
|
|
|
unix.SYS_RECVMMSG,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
|
|
|
uintptr(unsafe.Pointer(&msgs[0])),
|
|
|
|
uintptr(len(msgs)),
|
|
|
|
unix.MSG_WAITFORONE,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
|
|
|
return 0, &net.OpError{Op: "recvmmsg", Err: err}
|
|
|
|
}
|
|
|
|
|
|
|
|
return int(n), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
var rsa unix.RawSockaddrInet4
|
2019-11-19 18:00:20 +01:00
|
|
|
|
|
|
|
//TODO: sometimes addr is nil!
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
rsa.Family = unix.AF_INET
|
2019-11-19 18:00:20 +01:00
|
|
|
p := (*[2]byte)(unsafe.Pointer(&rsa.Port))
|
|
|
|
p[0] = byte(addr.Port >> 8)
|
|
|
|
p[1] = byte(addr.Port)
|
|
|
|
|
|
|
|
rsa.Addr[0] = byte(addr.IP & 0xff000000 >> 24)
|
|
|
|
rsa.Addr[1] = byte(addr.IP & 0x00ff0000 >> 16)
|
|
|
|
rsa.Addr[2] = byte(addr.IP & 0x0000ff00 >> 8)
|
|
|
|
rsa.Addr[3] = byte(addr.IP & 0x000000ff)
|
|
|
|
|
|
|
|
for {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
_, _, err := unix.Syscall6(
|
|
|
|
unix.SYS_SENDTO,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
|
|
|
uintptr(unsafe.Pointer(&b[0])),
|
|
|
|
uintptr(len(b)),
|
|
|
|
uintptr(0),
|
|
|
|
uintptr(unsafe.Pointer(&rsa)),
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
uintptr(unix.SizeofSockaddrInet4),
|
2019-11-19 18:00:20 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
|
|
|
return &net.OpError{Op: "sendto", Err: err}
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: handle incomplete writes
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *udpConn) reloadConfig(c *Config) {
|
|
|
|
b := c.GetInt("listen.read_buffer", 0)
|
|
|
|
if b > 0 {
|
|
|
|
err := u.SetRecvBuffer(b)
|
|
|
|
if err == nil {
|
|
|
|
s, err := u.GetRecvBuffer()
|
|
|
|
if err == nil {
|
|
|
|
l.WithField("size", s).Info("listen.read_buffer was set")
|
|
|
|
} else {
|
|
|
|
l.WithError(err).Warn("Failed to get listen.read_buffer")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
l.WithError(err).Error("Failed to set listen.read_buffer")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
b = c.GetInt("listen.write_buffer", 0)
|
|
|
|
if b > 0 {
|
|
|
|
err := u.SetSendBuffer(b)
|
|
|
|
if err == nil {
|
|
|
|
s, err := u.GetSendBuffer()
|
|
|
|
if err == nil {
|
|
|
|
l.WithField("size", s).Info("listen.write_buffer was set")
|
|
|
|
} else {
|
|
|
|
l.WithError(err).Warn("Failed to get listen.write_buffer")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
l.WithError(err).Error("Failed to set listen.write_buffer")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ua *udpAddr) Equals(t *udpAddr) bool {
|
|
|
|
if t == nil || ua == nil {
|
|
|
|
return t == nil && ua == nil
|
|
|
|
}
|
|
|
|
return ua.IP == t.IP && ua.Port == t.Port
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ua *udpAddr) Copy() *udpAddr {
|
|
|
|
return &udpAddr{
|
|
|
|
Port: ua.Port,
|
|
|
|
IP: ua.IP,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ua *udpAddr) String() string {
|
|
|
|
return fmt.Sprintf("%s:%v", int2ip(ua.IP), ua.Port)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ua *udpAddr) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(m{"ip": int2ip(ua.IP), "port": ua.Port})
|
|
|
|
}
|
|
|
|
|
|
|
|
func udp2ip(addr *udpAddr) net.IP {
|
|
|
|
return int2ip(addr.IP)
|
|
|
|
}
|
|
|
|
|
|
|
|
func udp2ipInt(addr *udpAddr) uint32 {
|
|
|
|
return addr.IP
|
|
|
|
}
|
|
|
|
|
|
|
|
func hostDidRoam(addr *udpAddr, newaddr *udpAddr) bool {
|
|
|
|
return !addr.Equals(newaddr)
|
|
|
|
}
|