mirror of
https://github.com/status-im/status-go.git
synced 2025-01-10 22:56:40 +00:00
eeca435064
Update vendor Integrate rendezvous into status node Add a test with failover using rendezvous Use multiple servers in client Use discovery V5 by default and test that node can be started with rendezvous discovet Fix linter Update rendezvous client to one with instrumented stream Address feedback Fix test with updated topic limits Apply several suggestions Change log to debug for request errors because we continue execution Remove web3js after rebase Update rendezvous package
111 lines
3.2 KiB
Go
111 lines
3.2 KiB
Go
package tcpreuse
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/rand"
|
|
"net"
|
|
)
|
|
|
|
type multiDialer struct {
|
|
loopback []*net.TCPAddr
|
|
unspecified []*net.TCPAddr
|
|
global *net.TCPAddr
|
|
}
|
|
|
|
func (d *multiDialer) Dial(network, addr string) (net.Conn, error) {
|
|
return d.DialContext(context.Background(), network, addr)
|
|
}
|
|
|
|
func randAddr(addrs []*net.TCPAddr) *net.TCPAddr {
|
|
if len(addrs) > 0 {
|
|
return addrs[rand.Intn(len(addrs))]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *multiDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
tcpAddr, err := net.ResolveTCPAddr(network, addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// We pick the source *port* based on the following algorithm.
|
|
//
|
|
// 1. If we're dialing loopback, choose a source-port in order of
|
|
// preference:
|
|
// 1. A port in-use by an explicit loopback listener.
|
|
// 2. A port in-use by a listener on an unspecified address (must
|
|
// also be listening on localhost).
|
|
// 3. A port in-use by a listener on a global address. We don't have
|
|
// any other better options (other than picking a random port).
|
|
// 2. If we're dialing a global address, choose a source-port in order
|
|
// of preference:
|
|
// 1. A port in-use by a listener on an unspecified address (the most
|
|
// general case).
|
|
// 2. A port in-use by a listener on the global address.
|
|
// 3. Fail on link-local dials (go-ipfs currently forbids this and I
|
|
// figured we could try lifting this restriction later).
|
|
//
|
|
//
|
|
// Note: We *always* dial from the unspecified address (regardless of
|
|
// the port we pick). In the future, we could use netlink (on Linux) to
|
|
// figure out the right source address but we're going to punt on that.
|
|
|
|
ip := tcpAddr.IP
|
|
source := d.global
|
|
switch {
|
|
case ip.IsLoopback():
|
|
switch {
|
|
case len(d.loopback) > 0:
|
|
source = randAddr(d.loopback)
|
|
case len(d.unspecified) > 0:
|
|
source = randAddr(d.unspecified)
|
|
}
|
|
case ip.IsGlobalUnicast():
|
|
switch {
|
|
case len(d.unspecified) > 0:
|
|
source = randAddr(d.unspecified)
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("undialable IP: %s", tcpAddr.IP)
|
|
}
|
|
return reuseDial(ctx, source, network, addr)
|
|
}
|
|
|
|
func newMultiDialer(unspec net.IP, listeners map[*listener]struct{}) dialer {
|
|
m := new(multiDialer)
|
|
for l := range listeners {
|
|
laddr := l.Addr().(*net.TCPAddr)
|
|
switch {
|
|
case laddr.IP.IsLoopback():
|
|
m.loopback = append(m.loopback, laddr)
|
|
case laddr.IP.IsGlobalUnicast():
|
|
// Different global ports? Crap.
|
|
//
|
|
// The *proper* way to deal with this is to, e.g., use
|
|
// netlink to figure out which source address we would
|
|
// normally use to dial a destination address and then
|
|
// pick one of the ports we're listening on on that
|
|
// source address. However, this is a pain in the ass.
|
|
//
|
|
// Instead, we're just going to always dial from the
|
|
// unspecified address with the first global port we
|
|
// find.
|
|
//
|
|
// TODO: Port priority? Addr priority?
|
|
if m.global == nil {
|
|
m.global = &net.TCPAddr{
|
|
IP: unspec,
|
|
Port: laddr.Port,
|
|
}
|
|
} else {
|
|
log.Warning("listening on external interfaces on multiple ports, will dial from %d, not %s", m.global, laddr)
|
|
}
|
|
case laddr.IP.IsUnspecified():
|
|
m.unspecified = append(m.unspecified, laddr)
|
|
}
|
|
}
|
|
return m
|
|
}
|