|
@@ -21,6 +21,7 @@ import (
|
|
|
type StdConn struct {
|
|
type StdConn struct {
|
|
|
udpConn *net.UDPConn
|
|
udpConn *net.UDPConn
|
|
|
rawConn syscall.RawConn
|
|
rawConn syscall.RawConn
|
|
|
|
|
+ sockFd int
|
|
|
isV4 bool
|
|
isV4 bool
|
|
|
l *logrus.Logger
|
|
l *logrus.Logger
|
|
|
batch int
|
|
batch int
|
|
@@ -61,9 +62,20 @@ func NewListener(l *logrus.Logger, ip netip.Addr, port int, multi bool, batch in
|
|
|
}
|
|
}
|
|
|
udpConn.LocalAddr().String()
|
|
udpConn.LocalAddr().String()
|
|
|
|
|
|
|
|
|
|
+ //steal the socket's fd for sending
|
|
|
|
|
+ var sockFd uintptr
|
|
|
|
|
+ err = rawConn.Control(func(fd uintptr) {
|
|
|
|
|
+ sockFd = fd
|
|
|
|
|
+ })
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ _ = udpConn.Close()
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return &StdConn{
|
|
return &StdConn{
|
|
|
udpConn: udpConn,
|
|
udpConn: udpConn,
|
|
|
rawConn: rawConn,
|
|
rawConn: rawConn,
|
|
|
|
|
+ sockFd: int(sockFd),
|
|
|
isV4: ip.Is4(),
|
|
isV4: ip.Is4(),
|
|
|
l: l,
|
|
l: l,
|
|
|
batch: batch,
|
|
batch: batch,
|
|
@@ -223,8 +235,64 @@ func (u *StdConn) ListenOut(r EncReader) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (u *StdConn) WriteTo(b []byte, ip netip.AddrPort) error {
|
|
func (u *StdConn) WriteTo(b []byte, ip netip.AddrPort) error {
|
|
|
- _, err := u.udpConn.WriteToUDPAddrPort(b, ip)
|
|
|
|
|
- return err
|
|
|
|
|
|
|
+ if u.isV4 {
|
|
|
|
|
+ return u.writeTo4(b, ip)
|
|
|
|
|
+ }
|
|
|
|
|
+ return u.writeTo6(b, ip)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (u *StdConn) writeTo6(b []byte, ip netip.AddrPort) error {
|
|
|
|
|
+ var rsa unix.RawSockaddrInet6
|
|
|
|
|
+ rsa.Family = unix.AF_INET6
|
|
|
|
|
+ rsa.Addr = ip.Addr().As16()
|
|
|
|
|
+ binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&rsa.Port))[:], ip.Port())
|
|
|
|
|
+
|
|
|
|
|
+ for {
|
|
|
|
|
+ _, _, err := unix.Syscall6(
|
|
|
|
|
+ unix.SYS_SENDTO,
|
|
|
|
|
+ uintptr(u.sockFd),
|
|
|
|
|
+ uintptr(unsafe.Pointer(&b[0])),
|
|
|
|
|
+ uintptr(len(b)),
|
|
|
|
|
+ uintptr(0),
|
|
|
|
|
+ uintptr(unsafe.Pointer(&rsa)),
|
|
|
|
|
+ uintptr(unix.SizeofSockaddrInet6),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ if err != 0 {
|
|
|
|
|
+ return &net.OpError{Op: "sendto", Err: err}
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (u *StdConn) writeTo4(b []byte, ip netip.AddrPort) error {
|
|
|
|
|
+ if !ip.Addr().Is4() {
|
|
|
|
|
+ return ErrInvalidIPv6RemoteForSocket
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var rsa unix.RawSockaddrInet4
|
|
|
|
|
+ rsa.Family = unix.AF_INET
|
|
|
|
|
+ rsa.Addr = ip.Addr().As4()
|
|
|
|
|
+ binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&rsa.Port))[:], ip.Port())
|
|
|
|
|
+
|
|
|
|
|
+ for {
|
|
|
|
|
+ _, _, err := unix.Syscall6(
|
|
|
|
|
+ unix.SYS_SENDTO,
|
|
|
|
|
+ uintptr(u.sockFd),
|
|
|
|
|
+ uintptr(unsafe.Pointer(&b[0])),
|
|
|
|
|
+ uintptr(len(b)),
|
|
|
|
|
+ uintptr(0),
|
|
|
|
|
+ uintptr(unsafe.Pointer(&rsa)),
|
|
|
|
|
+ uintptr(unix.SizeofSockaddrInet4),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ if err != 0 {
|
|
|
|
|
+ return &net.OpError{Op: "sendto", Err: err}
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (u *StdConn) ReloadConfig(c *config.C) {
|
|
func (u *StdConn) ReloadConfig(c *config.C) {
|