All checks were successful
Go Build Multi-Platform / build (amd64, windows) (push) Successful in 34s
Go Build Multi-Platform / build (amd64, freebsd) (push) Successful in 38s
Go Build Multi-Platform / build (amd64, linux) (push) Successful in 37s
Go Build Multi-Platform / build (arm, freebsd) (push) Successful in 32s
Go Build Multi-Platform / build (arm, linux) (push) Successful in 35s
Go Build Multi-Platform / build (arm64, darwin) (push) Successful in 34s
Go Build Multi-Platform / build (arm, windows) (push) Successful in 37s
Go Build Multi-Platform / build (arm64, freebsd) (push) Successful in 42s
Go Build Multi-Platform / Create Release (push) Has been skipped
Go Test Multi-Platform / Test (ubuntu-latest, amd64) (push) Successful in 1m29s
Go Revive Lint / lint (push) Successful in 47s
Run Gosec / tests (push) Successful in 1m3s
Go Build Multi-Platform / build (amd64, darwin) (push) Successful in 27s
Go Build Multi-Platform / build (arm64, linux) (push) Successful in 44s
Go Build Multi-Platform / build (arm64, windows) (push) Successful in 42s
Go Test Multi-Platform / Test (ubuntu-latest, arm64) (push) Successful in 1m5s
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
// +build linux
|
|
|
|
package interfaces
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"syscall"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"git.quad4.io/Networks/Reticulum-Go/pkg/debug"
|
|
)
|
|
|
|
func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|
tcpConn, ok := tc.conn.(*net.TCPConn)
|
|
if !ok {
|
|
return fmt.Errorf("not a TCP connection")
|
|
}
|
|
|
|
rawConn, err := tcpConn.SyscallConn()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get raw connection: %v", err)
|
|
}
|
|
|
|
var sockoptErr error
|
|
err = rawConn.Control(func(fd uintptr) {
|
|
var userTimeout, probeAfter, probeInterval, probeCount int
|
|
|
|
if tc.i2pTunneled {
|
|
userTimeout = I2P_USER_TIMEOUT_SEC * 1000
|
|
probeAfter = I2P_PROBE_AFTER_SEC
|
|
probeInterval = I2P_PROBE_INTERVAL_SEC
|
|
probeCount = I2P_PROBES_COUNT
|
|
} else {
|
|
userTimeout = TCP_USER_TIMEOUT_SEC * 1000
|
|
probeAfter = TCP_PROBE_AFTER_SEC
|
|
probeInterval = TCP_PROBE_INTERVAL_SEC
|
|
probeCount = TCP_PROBES_COUNT
|
|
}
|
|
|
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 18, userTimeout); err != nil {
|
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_USER_TIMEOUT", "error", err)
|
|
}
|
|
|
|
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
|
|
sockoptErr = fmt.Errorf("failed to enable SO_KEEPALIVE: %v", err)
|
|
return
|
|
}
|
|
|
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 4, probeAfter); err != nil {
|
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPIDLE", "error", err)
|
|
}
|
|
|
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 5, probeInterval); err != nil {
|
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPINTVL", "error", err)
|
|
}
|
|
|
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 6, probeCount); err != nil {
|
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPCNT", "error", err)
|
|
}
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("control failed: %v", err)
|
|
}
|
|
if sockoptErr != nil {
|
|
return sockoptErr
|
|
}
|
|
|
|
debug.Log(debug.DEBUG_VERBOSE, "TCP keepalive configured (Linux)", "i2p", tc.i2pTunneled)
|
|
return nil
|
|
}
|
|
|
|
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
|
return tc.setTimeoutsLinux()
|
|
}
|
|
|
|
func platformGetRTT(fd uintptr) time.Duration {
|
|
var info syscall.TCPInfo
|
|
infoLen := uint32(unsafe.Sizeof(info))
|
|
|
|
// TCP_INFO is 11 on Linux
|
|
// #nosec G103
|
|
_, _, errno := syscall.Syscall6(
|
|
syscall.SYS_GETSOCKOPT,
|
|
fd,
|
|
syscall.IPPROTO_TCP,
|
|
11, // TCP_INFO
|
|
uintptr(unsafe.Pointer(&info)),
|
|
uintptr(unsafe.Pointer(&infoLen)),
|
|
0,
|
|
)
|
|
|
|
if errno != 0 {
|
|
return 0
|
|
}
|
|
|
|
return time.Duration(info.Rtt) * time.Microsecond
|
|
}
|