@cryptotaxi247 / kubo / commits / 49733f4da

order addresses to give certain address types priority

License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>

Jeromy committed Oct 14, 2015 at 12:37 UTC 49733f4da1cde68f92e93f87de6e431c105d74cb
2 files changed +91 -5
p2p/net/swarm/dial_test.go
+36
@@ -2,6 +2,7 @@ package swarm
2
3 import (
4 "net"
5 + "sort"
6 "sync"
7 "testing"
8 "time"
@@ -438,3 +439,38 @@ func TestDialBackoffClears(t *testing.T) {
439 t.Log("correctly cleared backoff")
440 }
441 }
442 +
443 +func mkAddr(t *testing.T, s string) ma.Multiaddr {
444 + a, err := ma.NewMultiaddr(s)
445 + if err != nil {
446 + t.Fatal(err)
447 + }
448 +
449 + return a
450 +}
451 +
452 +func TestAddressSorting(t *testing.T) {
453 + u1 := mkAddr(t, "/ip4/152.12.23.53/udp/1234/utp")
454 + u2l := mkAddr(t, "/ip4/127.0.0.1/udp/1234/utp")
455 + local := mkAddr(t, "/ip4/127.0.0.1/tcp/1234")
456 + norm := mkAddr(t, "/ip4/6.5.4.3/tcp/1234")
457 +
458 + l := AddrList{local, u1, u2l, norm}
459 + sort.Sort(l)
460 +
461 + if !l[0].Equal(u2l) {
462 + t.Fatal("expected utp local addr to be sorted first: ", l[0])
463 + }
464 +
465 + if !l[1].Equal(u1) {
466 + t.Fatal("expected utp addr to be sorted second")
467 + }
468 +
469 + if !l[2].Equal(local) {
470 + t.Fatal("expected tcp localhost addr thid")
471 + }
472 +
473 + if !l[3].Equal(norm) {
474 + t.Fatal("expected normal addr last")
475 + }
476 +}
p2p/net/swarm/swarm_dial.go
+55 -5
@@ -1,10 +1,11 @@
1 package swarm
2
3 import (
4 + "bytes"
5 "errors"
6 "fmt"
6 - "math/rand"
7 "net"
8 + "sort"
9 "sync"
10 "time"
11
@@ -358,6 +359,9 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
359
360 func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remoteAddrs []ma.Multiaddr) (conn.Conn, error) {
361
362 + // sort addresses so preferred addresses are dialed sooner
363 + sort.Sort(AddrList(remoteAddrs))
364 +
365 // try to connect to one of the peer's known addresses.
366 // we dial concurrently to each of the addresses, which:
367 // * makes the process faster overall
@@ -404,10 +408,7 @@ func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remote
408 // to end early.
409 go func() {
410 limiter := make(chan struct{}, 8)
407 - // permute addrs so we try different sets first each time.
408 - for _, i := range rand.Perm(len(remoteAddrs)) {
409 -
410 - addr := remoteAddrs[i]
411 + for _, addr := range remoteAddrs {
412 // returns whatever ratelimiting is acceptable for workerAddr.
413 // may not rate limit at all.
414 rl := s.addrDialRateLimit(addr)
@@ -526,3 +527,52 @@ func isTCPMultiaddr(a ma.Multiaddr) bool {
527 p := a.Protocols()
528 return len(p) == 2 && (p[0].Name == "ip4" || p[0].Name == "ip6") && p[1].Name == "tcp"
529 }
530 +
531 +type AddrList []ma.Multiaddr
532 +
533 +func (al AddrList) Len() int {
534 + return len(al)
535 +}
536 +
537 +func (al AddrList) Swap(i, j int) {
538 + al[i], al[j] = al[j], al[i]
539 +}
540 +
541 +func (al AddrList) Less(i, j int) bool {
542 + a := al[i]
543 + b := al[j]
544 +
545 + // dial localhost addresses next, they should fail immediately
546 + lba := manet.IsIPLoopback(a)
547 + lbb := manet.IsIPLoopback(b)
548 + if lba {
549 + if !lbb {
550 + return true
551 + }
552 + }
553 +
554 + // dial utp and similar 'non-fd-consuming' addresses first
555 + fda := isFDCostlyTransport(a)
556 + fdb := isFDCostlyTransport(b)
557 + if !fda {
558 + if fdb {
559 + return true
560 + }
561 +
562 + // if neither consume fd's, assume equal ordering
563 + return false
564 + }
565 +
566 + // if 'b' doesnt take a file descriptor
567 + if !fdb {
568 + return false
569 + }
570 +
571 + // if 'b' is loopback and both take file descriptors
572 + if lbb {
573 + return false
574 + }
575 +
576 + // for the rest, just sort by bytes
577 + return bytes.Compare(a.Bytes(), b.Bytes()) > 0
578 +}