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

enable TCP keepalives #73

Merged
merged 2 commits into from
Feb 24, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ var DefaultConnectTimeout = 5 * time.Second

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

const keepAlivePeriod = 30 * time.Second

type canKeepAlive interface {
SetKeepAlive(bool) error
SetKeepAlivePeriod(time.Duration) error
}

var _ canKeepAlive = &net.TCPConn{}

func tryKeepAlive(conn net.Conn, keepAlive bool) {
keepAliveConn, ok := conn.(canKeepAlive)
if !ok {
log.Errorf("Can't set TCP keepalives.")
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved
return
}
if err := keepAliveConn.SetKeepAlive(keepAlive); err != nil {
log.Errorf("Failed to enable TCP keepalive: %s", err)
Copy link
Member

Choose a reason for hiding this comment

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

It's good to start off with an error, but this may have false positives (e.g., connection closed?). However, I assume that this method won't fail until we actually call close ourselves.

Also, return?

return
}
if err := keepAliveConn.SetKeepAlivePeriod(keepAlivePeriod); err != nil {
log.Errorf("Failed set keepalive period: %s", err)
}
}

// try to set linger on the connection, if possible.
func tryLinger(conn net.Conn, sec int) {
type canLinger interface {
Expand All @@ -33,17 +57,18 @@ func tryLinger(conn net.Conn, sec int) {
}
}

type lingerListener struct {
type tcpListener struct {
manet.Listener
sec int
}

func (ll *lingerListener) Accept() (manet.Conn, error) {
func (ll *tcpListener) Accept() (manet.Conn, error) {
c, err := ll.Listener.Accept()
if err != nil {
return nil, err
}
tryLinger(c, ll.sec)
tryKeepAlive(c, true)
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved
return c, nil
}

Expand Down Expand Up @@ -106,6 +131,7 @@ func (t *TcpTransport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID)
// 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)
tryKeepAlive(conn, true)
return t.Upgrader.UpgradeOutbound(ctx, t, conn, p)
}

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

Expand Down