@cryptotaxi247 / kubo / commits / 0135e3ebb

swarm + net: add explicit listen addresses

Juan Batiz-Benet committed Nov 5, 2014 at 03:59 UTC 0135e3ebbe2d8e676190d5832fec8c7a869ee1a0
8 files changed +138 -23
core/core.go
+21 -11
@@ -123,7 +123,12 @@ func NewIpfsNode(cfg *config.Config, online bool) (n *IpfsNode, err error) {
123 }
124
125 // setup the network
126 - n.Network, err = inet.NewIpfsNetwork(ctx, n.Identity, n.Peerstore, muxMap)
126 + listenAddrs, err := listenAddresses(cfg)
127 + if err != nil {
128 + return nil, err
129 + }
130 +
131 + n.Network, err = inet.NewIpfsNetwork(ctx, listenAddrs, n.Identity, n.Peerstore, muxMap)
132 if err != nil {
133 return nil, err
134 }
@@ -183,16 +188,6 @@ func initIdentity(cfg *config.Config, peers peer.Peerstore, online bool) (peer.P
188 return nil, err
189 }
190
186 - // address is optional
187 - if len(cfg.Addresses.Swarm) > 0 {
188 - maddr, err := ma.NewMultiaddr(cfg.Addresses.Swarm)
189 - if err != nil {
190 - return nil, err
191 - }
192 -
193 - peer.AddAddress(maddr)
194 - }
195 -
191 // when not online, don't need to parse private keys (yet)
192 if online {
193 skb, err := base64.StdEncoding.DecodeString(cfg.Identity.PrivKey)
@@ -233,3 +228,18 @@ func initConnections(ctx context.Context, cfg *config.Config, pstore peer.Peerst
228 }
229 }
230 }
231 +
232 +func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) {
233 + var listen []ma.Multiaddr
234 +
235 + if len(cfg.Addresses.Swarm) > 0 {
236 + maddr, err := ma.NewMultiaddr(cfg.Addresses.Swarm)
237 + if err != nil {
238 + return nil, fmt.Errorf("Failure to parse config.Addresses.Swarm: %s", cfg.Addresses.Swarm)
239 + }
240 +
241 + listen = append(listen, maddr)
242 + }
243 +
244 + return listen, nil
245 +}
net/interface.go
+10
@@ -6,6 +6,8 @@ import (
6 srv "github.com/jbenet/go-ipfs/net/service"
7 peer "github.com/jbenet/go-ipfs/peer"
8 ctxc "github.com/jbenet/go-ipfs/util/ctxcloser"
9 +
10 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
11 )
12
13 // Network is the interface IPFS uses for connecting to the world.
@@ -37,6 +39,14 @@ type Network interface {
39
40 // SendMessage sends given Message out
41 SendMessage(msg.NetMessage) error
42 +
43 + // ListenAddresses returns a list of addresses at which this network listens.
44 + ListenAddresses() []ma.Multiaddr
45 +
46 + // InterfaceListenAddresses returns a list of addresses at which this network
47 + // listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to
48 + // use the known local interfaces.
49 + InterfaceListenAddresses() ([]ma.Multiaddr, error)
50 }
51
52 // Sender interface for network services.
net/net.go
+15 -2
@@ -8,6 +8,7 @@ import (
8 ctxc "github.com/jbenet/go-ipfs/util/ctxcloser"
9
10 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
11 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
12 )
13
14 // IpfsNetwork implements the Network interface,
@@ -27,7 +28,7 @@ type IpfsNetwork struct {
28 }
29
30 // NewIpfsNetwork is the structure that implements the network interface
30 -func NewIpfsNetwork(ctx context.Context, local peer.Peer,
31 +func NewIpfsNetwork(ctx context.Context, listen []ma.Multiaddr, local peer.Peer,
32 peers peer.Peerstore, pmap *mux.ProtocolMap) (*IpfsNetwork, error) {
33
34 in := &IpfsNetwork{
@@ -37,7 +38,7 @@ func NewIpfsNetwork(ctx context.Context, local peer.Peer,
38 }
39
40 var err error
40 - in.swarm, err = swarm.NewSwarm(ctx, local, peers)
41 + in.swarm, err = swarm.NewSwarm(ctx, listen, local, peers)
42 if err != nil {
43 in.Close()
44 return nil, err
@@ -96,3 +97,15 @@ func (n *IpfsNetwork) GetPeerList() []peer.Peer {
97 func (n *IpfsNetwork) GetBandwidthTotals() (in uint64, out uint64) {
98 return n.muxer.GetBandwidthTotals()
99 }
100 +
101 +// ListenAddresses returns a list of addresses at which this network listens.
102 +func (n *IpfsNetwork) ListenAddresses() []ma.Multiaddr {
103 + return n.swarm.ListenAddresses()
104 +}
105 +
106 +// InterfaceListenAddresses returns a list of addresses at which this network
107 +// listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to
108 +// use the known local interfaces.
109 +func (n *IpfsNetwork) InterfaceListenAddresses() ([]ma.Multiaddr, error) {
110 + return n.swarm.InterfaceListenAddresses()
111 +}
net/swarm/addrs.go new
+74
@@ -0,0 +1,74 @@
1 +package swarm
2 +
3 +import (
4 + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
5 +
6 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
7 +)
8 +
9 +// ListenAddresses returns a list of addresses at which this swarm listens.
10 +func (s *Swarm) ListenAddresses() []ma.Multiaddr {
11 + addrs := make([]ma.Multiaddr, len(s.listeners))
12 + for i, l := range s.listeners {
13 + addrs[i] = l.Multiaddr()
14 + }
15 + return addrs
16 +}
17 +
18 +// InterfaceListenAddresses returns a list of addresses at which this swarm
19 +// listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to
20 +// use the known local interfaces.
21 +func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) {
22 + return resolveUnspecifiedAddresses(s.ListenAddresses())
23 +}
24 +
25 +// resolveUnspecifiedAddresses expands unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to
26 +// use the known local interfaces.
27 +func resolveUnspecifiedAddresses(unspecifiedAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
28 + var outputAddrs []ma.Multiaddr
29 +
30 + // todo optimize: only fetch these if we have a "any" addr.
31 + ifaceAddrs, err := interfaceAddresses()
32 + if err != nil {
33 + return nil, err
34 + }
35 +
36 + for _, a := range unspecifiedAddrs {
37 +
38 + // split address into its components
39 + split := ma.Split(a)
40 +
41 + // if first component (ip) is not unspecified, use it as is.
42 + if !manet.IsIPUnspecified(split[0]) {
43 + outputAddrs = append(outputAddrs)
44 + continue
45 + }
46 +
47 + // unspecified? add one address per interface.
48 + for _, ia := range ifaceAddrs {
49 + split[0] = ia
50 + joined := ma.Join(split...)
51 + outputAddrs = append(outputAddrs, joined)
52 + }
53 + }
54 +
55 + log.Info("InterfaceListenAddresses:", outputAddrs)
56 + return outputAddrs, nil
57 +}
58 +
59 +// interfaceAddresses returns a list of addresses associated with local machine
60 +func interfaceAddresses() ([]ma.Multiaddr, error) {
61 + maddrs, err := manet.InterfaceMultiaddrs()
62 + if err != nil {
63 + return nil, err
64 + }
65 +
66 + var nonLoopback []ma.Multiaddr
67 + for _, a := range maddrs {
68 + if !manet.IsIPLoopback(a) {
69 + nonLoopback = append(nonLoopback, a)
70 + }
71 + }
72 +
73 + return nonLoopback, nil
74 +}
net/swarm/conn.go
+13 -3
@@ -12,14 +12,14 @@ import (
12 )
13
14 // Open listeners for each network the swarm should listen on
15 -func (s *Swarm) listen() error {
15 +func (s *Swarm) listen(addrs []ma.Multiaddr) error {
16 hasErr := false
17 retErr := &ListenErr{
18 - Errors: make([]error, len(s.local.Addresses())),
18 + Errors: make([]error, len(addrs)),
19 }
20
21 // listen on every address
22 - for i, addr := range s.local.Addresses() {
22 + for i, addr := range addrs {
23 err := s.connListen(addr)
24 if err != nil {
25 hasErr = true
@@ -37,11 +37,21 @@ func (s *Swarm) listen() error {
37 // Listen for new connections on the given multiaddr
38 func (s *Swarm) connListen(maddr ma.Multiaddr) error {
39
40 + resolved, err := resolveUnspecifiedAddresses([]ma.Multiaddr{maddr})
41 + if err != nil {
42 + return err
43 + }
44 +
45 list, err := conn.Listen(s.Context(), maddr, s.local, s.peers)
46 if err != nil {
47 return err
48 }
49
50 + // add resolved local addresses to peer
51 + for _, addr := range resolved {
52 + s.local.AddAddress(addr)
53 + }
54 +
55 // make sure port can be reused. TOOD this doesn't work...
56 // if err := setSocketReuse(list); err != nil {
57 // return err
net/swarm/swarm.go
+3 -5
@@ -13,6 +13,7 @@ import (
13 ctxc "github.com/jbenet/go-ipfs/util/ctxcloser"
14
15 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
16 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
17 )
18
19 var log = u.Logger("swarm")
@@ -70,7 +71,7 @@ type Swarm struct {
71 }
72
73 // NewSwarm constructs a Swarm, with a Chan.
73 -func NewSwarm(ctx context.Context, local peer.Peer, ps peer.Peerstore) (*Swarm, error) {
74 +func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr, local peer.Peer, ps peer.Peerstore) (*Swarm, error) {
75 s := &Swarm{
76 Pipe: msg.NewPipe(10),
77 conns: conn.MultiConnMap{},
@@ -83,7 +84,7 @@ func NewSwarm(ctx context.Context, local peer.Peer, ps peer.Peerstore) (*Swarm,
84 s.ContextCloser = ctxc.NewContextCloser(ctx, s.close)
85
86 go s.fanOut()
86 - return s, s.listen()
87 + return s, s.listen(listenAddrs)
88 }
89
90 // close stops a swarm. It's the underlying function called by ContextCloser
@@ -210,6 +211,3 @@ func (s *Swarm) GetPeerList() []peer.Peer {
211 s.connsLock.RUnlock()
212 return out
213 }
213 -
214 -// Temporary to ensure that the Swarm always matches the Network interface as we are changing it
215 -// var _ Network = &Swarm{}
net/swarm/swarm_test.go
+1 -1
@@ -57,7 +57,7 @@ func makeSwarms(ctx context.Context, t *testing.T, addrs []string) ([]*Swarm, []
57 for _, addr := range addrs {
58 local := setupPeer(t, addr)
59 peerstore := peer.NewPeerstore()
60 - swarm, err := NewSwarm(ctx, local, peerstore)
60 + swarm, err := NewSwarm(ctx, local.Addresses(), local, peerstore)
61 if err != nil {
62 t.Fatal(err)
63 }
routing/dht/dht_test.go
+1 -1
@@ -24,7 +24,7 @@ func setupDHT(ctx context.Context, t *testing.T, p peer.Peer) *IpfsDHT {
24 peerstore := peer.NewPeerstore()
25
26 dhts := netservice.NewService(ctx, nil) // nil handler for now, need to patch it
27 - net, err := inet.NewIpfsNetwork(ctx, p, peerstore, &mux.ProtocolMap{
27 + net, err := inet.NewIpfsNetwork(ctx, p.Addresses(), p, peerstore, &mux.ProtocolMap{
28 mux.ProtocolID_Routing: dhts,
29 })
30 if err != nil {