mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 12:44:02 +03:00
FILE / ScuroNeko/mtg
network/init.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
106 lines
3.7 KiB
Go
106 lines
3.7 KiB
Go
// Network contains a default implementation of the network.
|
|
//
|
|
// Please see [mtglib.Network] interface to get some basic idea behind this
|
|
// abstraction.
|
|
//
|
|
// Some notable feature of this implementation:
|
|
//
|
|
// 1. It detaches dialer from a network. Dialer is something which implements a
|
|
// real dialer and network completes it with more higher level details.
|
|
// 2. It uses only TCP connections. Even for DNS it uses DNS-Over-HTTPS
|
|
// 3. It has some simple implementation of DNS cache which is good enough for
|
|
// our purpose.
|
|
// 4. It sets uses SO_REUSEPORT port if applicable.
|
|
package network
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/9seconds/mtg/v2/essentials"
|
|
)
|
|
|
|
const (
|
|
// DefaultTimeout is a default timeout for establishing TCP connection.
|
|
DefaultTimeout = 10 * time.Second
|
|
|
|
// DefaultHTTPTimeout defines a default timeout for making HTTP request.
|
|
DefaultHTTPTimeout = 10 * time.Second
|
|
|
|
// Deprecated:
|
|
//
|
|
// DefaultBufferSize defines a TCP buffer size. Both read and write, so for
|
|
// real size, please multiply this number by 2.
|
|
DefaultBufferSize = 16 * 1024 // 16 kib
|
|
|
|
// DefaultTCPKeepAlivePeriod defines a time period between 2 consequitive
|
|
// probes.
|
|
//
|
|
// Deprecated: use DefaultKeepAliveIdle and DefaultKeepAliveInterval instead.
|
|
DefaultTCPKeepAlivePeriod = 10 * time.Second
|
|
|
|
// DefaultKeepAliveIdle is the time a connection must be idle before
|
|
// the first keepalive probe is sent.
|
|
DefaultKeepAliveIdle = 30 * time.Second
|
|
|
|
// DefaultKeepAliveInterval is the time between consecutive keepalive
|
|
// probes.
|
|
DefaultKeepAliveInterval = 10 * time.Second
|
|
|
|
// DefaultKeepAliveCount is the number of unacknowledged probes before
|
|
// the connection is considered dead.
|
|
DefaultKeepAliveCount = 3
|
|
|
|
// ProxyDialerOpenThreshold is used for load balancing SOCKS5 dialer only.
|
|
//
|
|
// This dialer uses circuit breaker with of 3 stages: OPEN, HALF_OPEN and
|
|
// CLOSED. If state is CLOSED, all requests go in a normal mode. If you get
|
|
// more that ProxyDialerOpenThreshold errors, circuit breaker goes into OPEN
|
|
// mode.
|
|
//
|
|
// When circuit breaker is in OPEN mode, it forbids all request to a given
|
|
// proxy. But after ProxyDialerHalfOpenTimeout it gives a second chance and
|
|
// opens an access for a SINGLE request. If this request success, then circuit
|
|
// breaker closes, otherwise opens again.
|
|
//
|
|
// When circuit breaker is closed, it clears an error states each
|
|
// ProxyDialerResetFailuresTimeout.
|
|
ProxyDialerOpenThreshold = 5
|
|
|
|
// ProxyDialerHalfOpenTimeout defines a halfopen timeout for circuit breaker.
|
|
ProxyDialerHalfOpenTimeout = time.Minute
|
|
|
|
// ProxyDialerResetFailuresTimeout defines a timeout for resetting a failure.
|
|
ProxyDialerResetFailuresTimeout = 10 * time.Second
|
|
|
|
// DefaultDOHHostname defines a default IP address for DOH host. Since mtg is
|
|
// simple, please pass IP address here. We do not have bootstrap servers here
|
|
// embedded.
|
|
DefaultDOHHostname = "1.1.1.1"
|
|
|
|
// DNSTimeout defines a timeout for DNS queries.
|
|
DNSTimeout = 5 * time.Second
|
|
|
|
// tcpLingerTimeout defines a number of seconds to wait for sending
|
|
// unacknowledged data.
|
|
tcpLingerTimeout = 1
|
|
)
|
|
|
|
var (
|
|
// ErrCircuitBreakerOpened is returned when proxy is being accessed but
|
|
// circuit breaker is opened.
|
|
ErrCircuitBreakerOpened = errors.New("circuit breaker is opened")
|
|
|
|
// ErrCannotDialWithAllProxies is returned when load balancing client is
|
|
// trying to access proxies but all of them are failed.
|
|
ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
|
|
)
|
|
|
|
// Dialer defines an interface which is required to bootstrap a network
|
|
// instance from.
|
|
type Dialer interface {
|
|
Dial(network, address string) (essentials.Conn, error)
|
|
DialContext(ctx context.Context, network, address string) (essentials.Conn, error)
|
|
}
|