mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 01:24:02 +03:00
FILE / ScuroNeko/mtg
network/sockopts.go
Исходный файл и его история в репозитории.
TCP keepalive was configured (SetKeepAlivePeriod) but never actually enabled (SO_KEEPALIVE) on accepted client connections. Go 1.26's SetKeepAlivePeriod only sets TCP_KEEPIDLE — it does not call setsockopt(SO_KEEPALIVE, 1). Without SO_KEEPALIVE the kernel never sends probe packets, so dead connections from sleeping mobile clients linger until the idle timeout fires. Replace SetKeepAlive + SetKeepAlivePeriod with net.KeepAliveConfig (available since Go 1.24) for explicit per-socket control: Idle: 30s (time before first probe) Interval: 10s (between probes) Count: 3 (failed probes to declare dead) This detects dead connections in ~60s instead of relying on system defaults (tcp_keepalive_intvl=75s, probes=9 → up to 11 minutes). Increase the default idle timeout from 1 minute to 5 minutes. MTProto clients send ping_delay_disconnect every ~60s, which resets the idle timer. The previous 1-minute default created a race: if a ping arrived even 1–2 seconds late the relay was killed. A 5-minute window also survives typical mobile sleep periods (phone idle 2–5 min) where the NAT mapping is still alive and the connection can resume without reconnection. Ref: #132
47 lines
1.3 KiB
Go
47 lines
1.3 KiB
Go
package network
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
)
|
|
|
|
// SetClientSocketOptions tunes a TCP socket that represents a connection to
|
|
// end user (not Telegram service or fronting domain).
|
|
//
|
|
// bufferSize setting is deprecated and ignored.
|
|
func SetClientSocketOptions(conn net.Conn, bufferSize int) error {
|
|
return setCommonSocketOptions(conn.(*net.TCPConn)) //nolint: forcetypeassert
|
|
}
|
|
|
|
// SetServerSocketOptions tunes a TCP socket that represents a connection to
|
|
// remote server like Telegram or fronting domain (but not end user).
|
|
func SetServerSocketOptions(conn net.Conn, bufferSize int) error {
|
|
return setCommonSocketOptions(conn.(*net.TCPConn)) //nolint: forcetypeassert
|
|
}
|
|
|
|
func setCommonSocketOptions(conn *net.TCPConn) error {
|
|
if err := conn.SetKeepAliveConfig(net.KeepAliveConfig{
|
|
Enable: true,
|
|
Idle: DefaultKeepAliveIdle,
|
|
Interval: DefaultKeepAliveInterval,
|
|
Count: DefaultKeepAliveCount,
|
|
}); err != nil {
|
|
return fmt.Errorf("cannot configure TCP keepalive: %w", err)
|
|
}
|
|
|
|
if err := conn.SetLinger(tcpLingerTimeout); err != nil {
|
|
return fmt.Errorf("cannot set TCP linger timeout: %w", err)
|
|
}
|
|
|
|
rawConn, err := conn.SyscallConn()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot get underlying raw connection: %w", err)
|
|
}
|
|
|
|
if err := setSocketReuseAddrPort(rawConn); err != nil {
|
|
return fmt.Errorf("cannot setup SO_REUSEADDR/PORT: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|