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 {