notif.go 2.42 KB
Newer Older
1 2 3
package dht

import (
4
	"context"
5
	"io"
6
	"time"
7

8 9
	inet "github.com/libp2p/go-libp2p-net"
	ma "github.com/multiformats/go-multiaddr"
Jeromy's avatar
Jeromy committed
10
	mstream "github.com/multiformats/go-multistream"
11 12
)

13 14 15 16 17 18 19 20
// TODO: There is a race condition here where we could process notifications
// out-of-order and incorrectly mark some peers as DHT nodes (or not DHT nodes).
// The correct fix for this is nasty so I'm not really sure it's worth it.
// Incorrectly recording or failing to record a DHT node in the routing table
// isn't a big issue.

const dhtCheckTimeout = 10 * time.Second

21 22 23 24 25 26 27 28 29 30
// netNotifiee defines methods to be used with the IpfsDHT
type netNotifiee IpfsDHT

func (nn *netNotifiee) DHT() *IpfsDHT {
	return (*IpfsDHT)(nn)
}

func (nn *netNotifiee) Connected(n inet.Network, v inet.Conn) {
	dht := nn.DHT()
	select {
31
	case <-dht.Process().Closing():
32
		return
33
	default:
34
	}
35

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
	go func() {

		// Note: We *could* just check the peerstore to see if the remote side supports the dht
		// protocol, but its not clear that that information will make it into the peerstore
		// by the time this notification is sent. So just to be very careful, we brute force this
		// and open a new stream

		// TODO: There's a race condition here where the connection may
		// not be open (and we may sit here trying to connect). I've
		// added a timeout but that's not really the correct fix.

		ctx, cancel := context.WithTimeout(dht.Context(), dhtCheckTimeout)
		defer cancel()
		s, err := dht.host.NewStream(ctx, v.RemotePeer(), ProtocolDHT, ProtocolDHTOld)

		switch err {
		case nil:
			s.Close()
			// connected fine? full dht node
			dht.Update(dht.Context(), v.RemotePeer())
		case mstream.ErrNotSupported:
			// Client mode only, don't bother adding them to our routing table
		case io.EOF:
			// This is kindof an error, but it happens someone often so make it a warning
			log.Warningf("checking dht client type: %s", err)
		default:
			// real error? thats odd
			log.Errorf("checking dht client type: %s", err)
		}
	}()
66 67 68 69 70
}

func (nn *netNotifiee) Disconnected(n inet.Network, v inet.Conn) {
	dht := nn.DHT()
	select {
71
	case <-dht.Process().Closing():
72
		return
73
	default:
74
	}
75
	go dht.routingTable.Remove(v.RemotePeer())
76 77 78 79
}

func (nn *netNotifiee) OpenedStream(n inet.Network, v inet.Stream) {}
func (nn *netNotifiee) ClosedStream(n inet.Network, v inet.Stream) {}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
80 81
func (nn *netNotifiee) Listen(n inet.Network, a ma.Multiaddr)      {}
func (nn *netNotifiee) ListenClose(n inet.Network, a ma.Multiaddr) {}