mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-27 07:57:30 +08:00
order addresses to give certain address types priority
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
This commit is contained in:
@ -2,6 +2,7 @@ package swarm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -438,3 +439,38 @@ func TestDialBackoffClears(t *testing.T) {
|
|||||||
t.Log("correctly cleared backoff")
|
t.Log("correctly cleared backoff")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mkAddr(t *testing.T, s string) ma.Multiaddr {
|
||||||
|
a, err := ma.NewMultiaddr(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddressSorting(t *testing.T) {
|
||||||
|
u1 := mkAddr(t, "/ip4/152.12.23.53/udp/1234/utp")
|
||||||
|
u2l := mkAddr(t, "/ip4/127.0.0.1/udp/1234/utp")
|
||||||
|
local := mkAddr(t, "/ip4/127.0.0.1/tcp/1234")
|
||||||
|
norm := mkAddr(t, "/ip4/6.5.4.3/tcp/1234")
|
||||||
|
|
||||||
|
l := AddrList{local, u1, u2l, norm}
|
||||||
|
sort.Sort(l)
|
||||||
|
|
||||||
|
if !l[0].Equal(u2l) {
|
||||||
|
t.Fatal("expected utp local addr to be sorted first: ", l[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if !l[1].Equal(u1) {
|
||||||
|
t.Fatal("expected utp addr to be sorted second")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !l[2].Equal(local) {
|
||||||
|
t.Fatal("expected tcp localhost addr thid")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !l[3].Equal(norm) {
|
||||||
|
t.Fatal("expected normal addr last")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package swarm
|
package swarm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -358,6 +359,9 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
|
|||||||
|
|
||||||
func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remoteAddrs []ma.Multiaddr) (conn.Conn, error) {
|
func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remoteAddrs []ma.Multiaddr) (conn.Conn, error) {
|
||||||
|
|
||||||
|
// sort addresses so preferred addresses are dialed sooner
|
||||||
|
sort.Sort(AddrList(remoteAddrs))
|
||||||
|
|
||||||
// try to connect to one of the peer's known addresses.
|
// try to connect to one of the peer's known addresses.
|
||||||
// we dial concurrently to each of the addresses, which:
|
// we dial concurrently to each of the addresses, which:
|
||||||
// * makes the process faster overall
|
// * makes the process faster overall
|
||||||
@ -404,10 +408,7 @@ func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remote
|
|||||||
// to end early.
|
// to end early.
|
||||||
go func() {
|
go func() {
|
||||||
limiter := make(chan struct{}, 8)
|
limiter := make(chan struct{}, 8)
|
||||||
// permute addrs so we try different sets first each time.
|
for _, addr := range remoteAddrs {
|
||||||
for _, i := range rand.Perm(len(remoteAddrs)) {
|
|
||||||
|
|
||||||
addr := remoteAddrs[i]
|
|
||||||
// returns whatever ratelimiting is acceptable for workerAddr.
|
// returns whatever ratelimiting is acceptable for workerAddr.
|
||||||
// may not rate limit at all.
|
// may not rate limit at all.
|
||||||
rl := s.addrDialRateLimit(addr)
|
rl := s.addrDialRateLimit(addr)
|
||||||
@ -526,3 +527,52 @@ func isTCPMultiaddr(a ma.Multiaddr) bool {
|
|||||||
p := a.Protocols()
|
p := a.Protocols()
|
||||||
return len(p) == 2 && (p[0].Name == "ip4" || p[0].Name == "ip6") && p[1].Name == "tcp"
|
return len(p) == 2 && (p[0].Name == "ip4" || p[0].Name == "ip6") && p[1].Name == "tcp"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddrList []ma.Multiaddr
|
||||||
|
|
||||||
|
func (al AddrList) Len() int {
|
||||||
|
return len(al)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al AddrList) Swap(i, j int) {
|
||||||
|
al[i], al[j] = al[j], al[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (al AddrList) Less(i, j int) bool {
|
||||||
|
a := al[i]
|
||||||
|
b := al[j]
|
||||||
|
|
||||||
|
// dial localhost addresses next, they should fail immediately
|
||||||
|
lba := manet.IsIPLoopback(a)
|
||||||
|
lbb := manet.IsIPLoopback(b)
|
||||||
|
if lba {
|
||||||
|
if !lbb {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dial utp and similar 'non-fd-consuming' addresses first
|
||||||
|
fda := isFDCostlyTransport(a)
|
||||||
|
fdb := isFDCostlyTransport(b)
|
||||||
|
if !fda {
|
||||||
|
if fdb {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// if neither consume fd's, assume equal ordering
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if 'b' doesnt take a file descriptor
|
||||||
|
if !fdb {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if 'b' is loopback and both take file descriptors
|
||||||
|
if lbb {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// for the rest, just sort by bytes
|
||||||
|
return bytes.Compare(a.Bytes(), b.Bytes()) > 0
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user