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 af1f309 commit bd1b98f
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

2 comments on commit bd1b98f

@lovishpuri
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'func SetLinger' is never actually used in libp2p, could you please add a Conn type which has SetLinger and SetKeepAlive methods ?

@Stebalien
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lovishpuri in the future, please file an issue. Most people won't read comments on commits.

In this case, that's not going to work:

  1. "Linger" is TCP specific, and the libp2p Conn type isn't TCP specific.
  2. We definitely do call SetLinker. That's what this commit is doing (setting it on accept and on dial).

Please sign in to comment.