Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Commit

Permalink
set linger to 0 for both inbound and outbound connections
Browse files Browse the repository at this point in the history
This causes us to send RST packets instead of FIN packets when closing
connections and means connections immediately enter the "reset" state instead of
entering the TIME-WAIT state.

Importantly, this means we can immediately reuse the 5-tuple and reconnect.
  • Loading branch information
Stebalien committed Apr 4, 2019
1 parent 528218d commit 6fa9ced
Showing 1 changed file with 29 additions and 0 deletions.
29 changes: 29 additions & 0 deletions tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tcp

import (
"context"
"net"
"time"

logging "github.com/ipfs/go-log"
Expand All @@ -20,6 +21,29 @@ var DefaultConnectTimeout = 5 * time.Second

var log = logging.Logger("tcp-tpt")

// try to set linger on the connection, if possible.
func tryLinger(conn net.Conn, sec int) {
if lingerConn, ok := conn.(interface {
SetLinger(int) error
}); ok {
_ = lingerConn.SetLinger(sec)
}
}

type lingerListener struct {
manet.Listener
sec int
}

func (ll *lingerListener) Accept() (manet.Conn, error) {
c, err := ll.Listener.Accept()
if err != nil {
return nil, err
}
tryLinger(c, ll.sec)
return c, nil
}

// TcpTransport is the TCP transport.
type TcpTransport struct {
// Connection upgrader for upgrading insecure stream connections to
Expand Down Expand Up @@ -73,6 +97,10 @@ func (t *TcpTransport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID)
if err != nil {
return nil, err
}
// Set linger to 0 so we never get stuck in the TIME-WAIT state. When
// linger is 0, connections are _reset_ instead of closed with a FIN.
// This means we can immediately reuse the 5-tuple and reconnect.
tryLinger(conn, 0)
return t.Upgrader.UpgradeOutbound(ctx, t, conn, p)
}

Expand All @@ -94,6 +122,7 @@ func (t *TcpTransport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {
if err != nil {
return nil, err
}
list = &lingerListener{list, 0}
return t.Upgrader.UpgradeListener(t, list), nil
}

Expand Down

0 comments on commit 6fa9ced

Please sign in to comment.