mirror of
https://github.com/soypat/lneto.git
synced 2026-09-08 15:59:10 +00:00
merge main fixes
This commit is contained in:
@@ -12,11 +12,14 @@ import (
|
|||||||
|
|
||||||
"github.com/soypat/lneto"
|
"github.com/soypat/lneto"
|
||||||
"github.com/soypat/lneto/ethernet"
|
"github.com/soypat/lneto/ethernet"
|
||||||
|
"github.com/soypat/lneto/tcp"
|
||||||
|
"github.com/soypat/lneto/tcp/rto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestTCPRetransmitsLostSegment drops exactly one data segment and requires the
|
// TestTCPRetransmitsLostSegment drops exactly one data segment and requires the
|
||||||
// bytes to arrive anyway, which is what [TCPPoolConfig.NanoTime] already promises
|
// bytes to arrive anyway. It covers [TCPPoolConfig.NewPolicy] reaching the
|
||||||
// in its own documentation. Without a LossRecovery installed the loss is terminal.
|
// pooled and dialed connections alike: without a [tcp.Policy] installed the
|
||||||
|
// loss is terminal, which is what this test asserts against.
|
||||||
func TestTCPRetransmitsLostSegment(t *testing.T) {
|
func TestTCPRetransmitsLostSegment(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
MTU = ethernet.MaxMTU
|
MTU = ethernet.MaxMTU
|
||||||
@@ -55,6 +58,13 @@ func TestTCPRetransmitsLostSegment(t *testing.T) {
|
|||||||
EstablishedTimeout: 30 * time.Second,
|
EstablishedTimeout: 30 * time.Second,
|
||||||
ClosingTimeout: 30 * time.Second,
|
ClosingTimeout: 30 * time.Second,
|
||||||
NewBackoff: func() lneto.BackoffStrategy { return backoffYield },
|
NewBackoff: func() lneto.BackoffStrategy { return backoffYield },
|
||||||
|
NewPolicy: func() tcp.Policy {
|
||||||
|
timer := new(rto.Timer)
|
||||||
|
if err := timer.Configure(func() int64 { return time.Now().UnixNano() }); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return timer
|
||||||
|
},
|
||||||
}
|
}
|
||||||
svGo := sv.StackBlocking(backoffYield).StackGo(StackGoConfig{ListenerPoolConfig: pool})
|
svGo := sv.StackBlocking(backoffYield).StackGo(StackGoConfig{ListenerPoolConfig: pool})
|
||||||
clGo := client.StackBlocking(backoffYield).StackGo(StackGoConfig{
|
clGo := client.StackBlocking(backoffYield).StackGo(StackGoConfig{
|
||||||
|
|||||||
+8
-6
@@ -176,17 +176,19 @@ func (s StackGo) SocketNetip(ctx context.Context, network string, family, sotype
|
|||||||
if isDial {
|
if isDial {
|
||||||
var conn tcp.Conn
|
var conn tcp.Conn
|
||||||
// DIAL TCP: active connection a.k.a TCP Client branch.
|
// DIAL TCP: active connection a.k.a TCP Client branch.
|
||||||
err = conn.Configure(tcp.ConnConfig{
|
conncfg := tcp.ConnConfig{
|
||||||
// TODO(pato): Eventually add UDP configuration. we use TCP for now for simplicity's sake.
|
// TODO(pato): Eventually add UDP configuration. we use TCP for now for simplicity's sake.
|
||||||
TxBuf: make([]byte, s.plcfg.TxBufSize),
|
TxBuf: make([]byte, s.plcfg.TxBufSize),
|
||||||
RxBuf: make([]byte, s.plcfg.RxBufSize),
|
RxBuf: make([]byte, s.plcfg.RxBufSize),
|
||||||
TxPacketQueueSize: s.plcfg.QueueSize,
|
TxPacketQueueSize: s.plcfg.QueueSize,
|
||||||
RWBackoff: s.plcfg.NewBackoff(),
|
RWBackoff: s.plcfg.NewBackoff(),
|
||||||
// A dialed connection needs a retransmission timer as much as a
|
}
|
||||||
// pooled one. See [NewTCPPool].
|
if s.plcfg.NewPolicy != nil {
|
||||||
LossRecovery: new(tcp.RTO),
|
// A dialed connection needs loss recovery as much as a pooled
|
||||||
Nanotime: s.blk.nanotime,
|
// one. See [TCPPoolConfig.NewPolicy].
|
||||||
})
|
conncfg.Policy = s.plcfg.NewPolicy()
|
||||||
|
}
|
||||||
|
err = conn.Configure(conncfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-7
@@ -42,8 +42,9 @@ type TCPPoolConfig struct {
|
|||||||
ConnLogger *slog.Logger
|
ConnLogger *slog.Logger
|
||||||
|
|
||||||
// NanoTime returns the current monotonic time in nanoseconds.
|
// NanoTime returns the current monotonic time in nanoseconds.
|
||||||
// Used for pool timeout tracking and passed to each [tcp.Conn] for
|
// Used for pool timeout tracking. If nil, defaults to time.Now().UnixNano().
|
||||||
// retransmission timing (RFC 6298). If nil, defaults to time.Now().UnixNano().
|
// Retransmission timing is not driven by this clock: a [tcp.Policy] carries
|
||||||
|
// its own. See NewPolicy.
|
||||||
NanoTime func() int64
|
NanoTime func() int64
|
||||||
// EstablishedTimeout sets the timeout for a TCP connection since it is acquired until it is established.
|
// EstablishedTimeout sets the timeout for a TCP connection since it is acquired until it is established.
|
||||||
// If the connection does not establish in this time it will be closed by the pool.
|
// If the connection does not establish in this time it will be closed by the pool.
|
||||||
@@ -56,6 +57,9 @@ type TCPPoolConfig struct {
|
|||||||
// NewBackoff returns the backoff to use for every newly configured TCP connection. Must be non-nil.
|
// NewBackoff returns the backoff to use for every newly configured TCP connection. Must be non-nil.
|
||||||
// This should always return a static(non-method) function unless you know what you are doing.
|
// This should always return a static(non-method) function unless you know what you are doing.
|
||||||
NewBackoff func() lneto.BackoffStrategy
|
NewBackoff func() lneto.BackoffStrategy
|
||||||
|
// NewPolicy if non-nil creates a [tcp.Policy] for each [tcp.Conn] used by the configured Listener.
|
||||||
|
// NewPolicy should not return reused policies unless the algorithm is stateless. See [tcp.Policy] for more information.
|
||||||
|
NewPolicy func() tcp.Policy
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTCPPool(cfg TCPPoolConfig) (*TCPPool, error) {
|
func NewTCPPool(cfg TCPPoolConfig) (*TCPPool, error) {
|
||||||
@@ -87,11 +91,11 @@ func NewTCPPool(cfg TCPPoolConfig) (*TCPPool, error) {
|
|||||||
TxPacketQueueSize: cfg.QueueSize,
|
TxPacketQueueSize: cfg.QueueSize,
|
||||||
Logger: cfg.ConnLogger,
|
Logger: cfg.ConnLogger,
|
||||||
RWBackoff: cfg.NewBackoff(),
|
RWBackoff: cfg.NewBackoff(),
|
||||||
// Retransmission timing, as NanoTime's contract promises. One RTO per
|
}
|
||||||
// connection: it shadows that connection's send sequence space and so
|
if cfg.NewPolicy != nil {
|
||||||
// cannot be shared.
|
// One Policy per connection: it shadows that connection's send
|
||||||
LossRecovery: new(tcp.RTO),
|
// sequence space and so cannot be shared.
|
||||||
Nanotime: pool.now,
|
conncfg.Policy = cfg.NewPolicy()
|
||||||
}
|
}
|
||||||
err := pool.conns[i].Configure(conncfg)
|
err := pool.conns[i].Configure(conncfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user