From f1566e232723d14b042a88be82234150ee8104c0 Mon Sep 17 00:00:00 2001 From: Juan Batiz-Benet Date: Wed, 8 Apr 2015 00:04:58 -0700 Subject: [PATCH] reuseport: env var to turn it off reuseport is a hack. It is necessary for us to do certain kinds of tcp nat traversal. Ideally, reuseport would be available in go: https://github.com/golang/go/issues/9661 But until that issue is fixed, we're stuck with this. In some cases, reuseport is strictly a detriment: nodes are not NATed. This commit introduces an ENV var IPFS_REUSEPORT that can be set to false to avoid using reuseport entirely: IPFS_REUSEPORT=false ipfs daemon This approach addresses our current need. It could become a config var if necessary. If reuseport continues to give problems, we should look into improving it. --- p2p/net/conn/dial.go | 2 +- p2p/net/conn/listen.go | 2 +- p2p/net/conn/reuseport.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 p2p/net/conn/reuseport.go diff --git a/p2p/net/conn/dial.go b/p2p/net/conn/dial.go index 1bf66a634be..0090678d6d4 100644 --- a/p2p/net/conn/dial.go +++ b/p2p/net/conn/dial.go @@ -118,7 +118,7 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee // make a copy of the manet.Dialer, we may need to change its timeout. madialer := d.Dialer - if laddr != nil && reuseport.Available() { + if laddr != nil && reuseportIsAvailable() { // we're perhaps going to dial twice. half the timeout, so we can afford to. // otherwise our context would expire right after the first dial. madialer.Dialer.Timeout = (madialer.Dialer.Timeout / 2) diff --git a/p2p/net/conn/listen.go b/p2p/net/conn/listen.go index fd166c273b4..d60c0ba3ad0 100644 --- a/p2p/net/conn/listen.go +++ b/p2p/net/conn/listen.go @@ -169,7 +169,7 @@ func manetListen(addr ma.Multiaddr) (manet.Listener, error) { return nil, err } - if reuseport.Available() { + if reuseportIsAvailable() { nl, err := reuseport.Listen(network, naddr) if err == nil { // hey, it worked! diff --git a/p2p/net/conn/reuseport.go b/p2p/net/conn/reuseport.go new file mode 100644 index 00000000000..359c5231530 --- /dev/null +++ b/p2p/net/conn/reuseport.go @@ -0,0 +1,35 @@ +package conn + +import ( + "os" + "strings" + + reuseport "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-reuseport" +) + +// envReuseport is the env variable name used to turn off reuse port. +// It default to true. +const envReuseport = "IPFS_REUSEPORT" + +// envReuseportVal stores the value of envReuseport. defaults to true. +var envReuseportVal = true + +func init() { + v := strings.ToLower(os.Getenv(envReuseport)) + if v == "false" || v == "f" || v == "0" { + envReuseportVal = false + log.Infof("REUSEPORT disabled (IPFS_REUSEPORT=%s)", v) + } +} + +// reuseportIsAvailable returns whether reuseport is available to be used. This +// is here because we want to be able to turn reuseport on and off selectively. +// For now we use an ENV variable, as this handles our pressing need: +// +// IPFS_REUSEPORT=false ipfs daemon +// +// If this becomes a sought after feature, we could add this to the config. +// In the end, reuseport is a stop-gap. +func reuseportIsAvailable() bool { + return envReuseportVal && reuseport.Available() +}