@cryptotaxi247 / kubo / commits / ca757c66f

p2p/nat: managed by host now.

Exposing the NAT to the core is unnecessary. The Host can take care of it. If a need emerges, we can address it then.

Juan Batiz-Benet committed Jan 26, 2015 at 09:44 UTC ca757c66ff20a60d5abbb4cf85f5ac6c5da0ca2a
4 files changed +90 -16
core/core.go
+1 -12
@@ -18,7 +18,6 @@ import (
18 ic "github.com/jbenet/go-ipfs/p2p/crypto"
19 p2phost "github.com/jbenet/go-ipfs/p2p/host"
20 p2pbhost "github.com/jbenet/go-ipfs/p2p/host/basic"
21 - inat "github.com/jbenet/go-ipfs/p2p/nat"
21 swarm "github.com/jbenet/go-ipfs/p2p/net/swarm"
22 addrutil "github.com/jbenet/go-ipfs/p2p/net/swarm/addr"
23 peer "github.com/jbenet/go-ipfs/p2p/peer"
@@ -422,7 +421,7 @@ func constructPeerHost(ctx context.Context, cfg *config.Config, id peer.ID, ps p
421 return nil, debugerror.Wrap(err)
422 }
423
425 - peerhost := p2pbhost.New(network)
424 + peerhost := p2pbhost.New(network, p2pbhost.NATPortMap)
425 // explicitly set these as our listen addrs.
426 // (why not do it inside inet.NewNetwork? because this way we can
427 // listen on addresses without necessarily advertising those publicly.)
@@ -432,16 +431,6 @@ func constructPeerHost(ctx context.Context, cfg *config.Config, id peer.ID, ps p
431 }
432 log.Infof("Swarm listening at: %s", addrs)
433
435 - nat := inat.DiscoverGateway()
436 - if nat != nil {
437 - nat.PortMapAddrs(filteredAddrs)
438 - mapAddrs := nat.ExternalAddrs()
439 - if len(mapAddrs) > 0 {
440 - log.Infof("NAT mapping addrs: %s", mapAddrs)
441 - addrs = append(addrs, mapAddrs...)
442 - }
443 - }
444 -
434 ps.AddAddresses(id, addrs)
435 return peerhost, nil
436 }
p2p/host/basic/basic_host.go
+77 -2
@@ -1,10 +1,15 @@
1 package basichost
2
3 import (
4 + "sync"
5 +
6 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
7 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8 + goprocess "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
9
10 eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog"
11
12 + inat "github.com/jbenet/go-ipfs/p2p/nat"
13 inet "github.com/jbenet/go-ipfs/p2p/net"
14 peer "github.com/jbenet/go-ipfs/p2p/peer"
15 protocol "github.com/jbenet/go-ipfs/p2p/protocol"
@@ -14,20 +19,35 @@ import (
19
20 var log = eventlog.Logger("p2p/host/basic")
21
22 +type Option int
23 +
24 +const (
25 + NATPortMap Option = iota
26 +)
27 +
28 type BasicHost struct {
29 network inet.Network
30 mux *protocol.Mux
31 ids *identify.IDService
32 relay *relay.RelayService
33 +
34 + natmu sync.Mutex
35 + nat *inat.NAT
36 +
37 + proc goprocess.Process
38 }
39
40 // New constructs and sets up a new *BasicHost with given Network
25 -func New(net inet.Network) *BasicHost {
41 +func New(net inet.Network, opts ...Option) *BasicHost {
42 h := &BasicHost{
43 network: net,
44 mux: protocol.NewMux(),
45 }
46
47 + h.proc = goprocess.WithTeardown(func() error {
48 + return h.Network().Close()
49 + })
50 +
51 // setup host services
52 h.ids = identify.NewIDService(h)
53 h.relay = relay.NewRelayService(h, h.Mux().HandleSync)
@@ -35,9 +55,48 @@ func New(net inet.Network) *BasicHost {
55 net.SetConnHandler(h.newConnHandler)
56 net.SetStreamHandler(h.newStreamHandler)
57
58 + for _, o := range opts {
59 + switch o {
60 + case NATPortMap:
61 + h.setupNATPortMap()
62 + }
63 + }
64 +
65 return h
66 }
67
68 +func (h *BasicHost) setupNATPortMap() {
69 + // do this asynchronously to avoid blocking daemon startup
70 +
71 + h.proc.Go(func(worker goprocess.Process) {
72 + nat := inat.DiscoverNAT()
73 + if nat == nil { // no nat, or failed to get it.
74 + return
75 + }
76 +
77 + select {
78 + case <-worker.Closing():
79 + nat.Close()
80 + return
81 + default:
82 + }
83 +
84 + // wire up the nat to close when proc closes.
85 + h.proc.AddChild(nat.Process())
86 +
87 + h.natmu.Lock()
88 + h.nat = nat
89 + h.natmu.Unlock()
90 +
91 + addrs := h.Network().ListenAddresses()
92 + nat.PortMapAddrs(addrs)
93 + mapAddrs := nat.ExternalAddrs()
94 + if len(mapAddrs) > 0 {
95 + log.Infof("NAT mapping addrs: %s", mapAddrs)
96 + }
97 + })
98 +}
99 +
100 // newConnHandler is the remote-opened conn handler for inet.Network
101 func (h *BasicHost) newConnHandler(c inet.Conn) {
102 h.ids.IdentifyConn(c)
@@ -143,7 +202,23 @@ func (h *BasicHost) dialPeer(ctx context.Context, p peer.ID) error {
202 return nil
203 }
204
205 +func (h *BasicHost) Addrs() []ma.Multiaddr {
206 + addrs, err := h.Network().InterfaceListenAddresses()
207 + if err != nil {
208 + log.Debug("error retrieving network interface addrs")
209 + }
210 +
211 + h.natmu.Lock()
212 + nat := h.nat
213 + h.natmu.Unlock()
214 + if nat != nil {
215 + addrs = append(addrs, nat.ExternalAddrs()...)
216 + }
217 +
218 + return addrs
219 +}
220 +
221 // Close shuts down the Host's services (network, etc).
222 func (h *BasicHost) Close() error {
148 - return h.Network().Close()
223 + return h.proc.Close()
224 }
p2p/host/host.go
+4
@@ -2,6 +2,7 @@ package host
2
3 import (
4 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
5 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
6
7 inet "github.com/jbenet/go-ipfs/p2p/net"
8 peer "github.com/jbenet/go-ipfs/p2p/peer"
@@ -23,6 +24,9 @@ type Host interface {
24 // Peerstore returns the Host's repository of Peer Addresses and Keys.
25 Peerstore() peer.Peerstore
26
27 + // Returns the listen addresses of the Host
28 + Addrs() []ma.Multiaddr
29 +
30 // Networks returns the Network interface of the Host
31 Network() inet.Network
32
p2p/nat/nat.go
+8 -2
@@ -29,9 +29,9 @@ var log = eventlog.Logger("nat")
29 // Port mappings are renewed every (MappingDuration / 3)
30 const MappingDuration = time.Second * 60
31
32 -// DiscoverGateway looks for a NAT device in the network and
32 +// DiscoverNAT looks for a NAT device in the network and
33 // returns an object that can manage port mappings.
34 -func DiscoverGateway() *NAT {
34 +func DiscoverNAT() *NAT {
35 nat, err := nat.DiscoverGateway()
36 if err != nil {
37 log.Debug("DiscoverGateway error:", err)
@@ -72,6 +72,12 @@ func (nat *NAT) Close() error {
72 return nat.proc.Close()
73 }
74
75 +// Process returns the nat's life-cycle manager, for making it listen
76 +// to close signals.
77 +func (nat *NAT) Process() goprocess.Process {
78 + return nat.proc
79 +}
80 +
81 // Notifier is an object that assists NAT in notifying listeners.
82 // It is implemented using github.com/jbenet/go-ipfs/thirdparty/notifier
83 type Notifier struct {