/
make_routed_host.go
140 lines (111 loc) · 4 KB
/
make_routed_host.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package archon_dht
import (
"context"
"fmt"
"log"
"regexp"
"time"
"github.com/libp2p/go-libp2p-core/peer"
ds "github.com/ipfs/go-datastore"
dsync "github.com/ipfs/go-datastore/sync"
ma "github.com/multiformats/go-multiaddr"
dht "github.com/archoncloud/archon-dht/mods/kad-dht-mod"
archonSecio "github.com/archoncloud/archon-dht/mods/go-libp2p-secio-mod"
"github.com/libp2p/go-libp2p"
rhost "github.com/libp2p/go-libp2p/p2p/host/routed"
)
var (
AutoNATServiceDialTimeout = 15 * time.Second
AutoNATServiceResetInterval = 1 * time.Minute
AutoNATServiceThrottle = 3
)
// makeRoutedHost creates a LibP2P host with a random peer ID listening on the
// given multiaddress. It will use secio if secio is true. It will bootstrap using the
// provided PeerInfo
func makeRoutedHost(config DHTConnectionConfig, bootstrapPeers []peer.AddrInfo) (*rhost.RoutedHost, *dht.IpfsDHT, error) {
// If the seed is 1, will use real cryptographic randomness.
// Otherwise, use a deterministic source of randomness to make
// generated keys stay the same across multiple runs
priv, err := GetRSAKey(config.Seed)
if err != nil {
return nil, nil, err
}
var myPartialMultiAddress string
myPartialMultiAddress = config.MyPartialMultiAddress
preTcp := regexp.MustCompile("^.*/tcp/")
port := preTcp.ReplaceAllString(myPartialMultiAddress, "")
// address factory
publicPeer, err := ma.NewMultiaddr(myPartialMultiAddress)
if err != nil {
return nil, nil, err
}
addressFactory := func(addrs []ma.Multiaddr) []ma.Multiaddr {
if publicPeer != nil {
addrs = append(addrs, publicPeer)
}
return addrs
}
archonSecurity := archonSecio.SetPermissionedSecureTransport(config.PermissionLayer.ID())
opts := []libp2p.Option{
libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/" + port),
libp2p.Identity(priv),
libp2p.DefaultTransports,
libp2p.DefaultMuxers,
libp2p.Security(archonSecio.ID, archonSecurity),
libp2p.AddrsFactory(addressFactory),
libp2p.NATPortMap(),
}
ctx := context.Background()
basicHost, err := libp2p.New(ctx, opts...)
if err != nil {
return nil, nil, err
}
// Construct a datastore (needed by the DHT). This is just a simple, in-memory thread-safe datastore.
dstore := dsync.MutexWrap(ds.NewMapDatastore())
// Make the DHT
dht := dht.NewDHT(ctx, basicHost, dstore, config.PermissionLayer)
archonValidator := new(ArchonValidator)
// see validator.go
archonValidator.PermissionLayer = config.PermissionLayer
dht.Validator = archonValidator
// Make the routed host
routedHost := rhost.Wrap(basicHost, dht)
// self checks if registered with smart contract in init,
// which calls this function
if !config.IAmBootstrap { // ask george@archon.cloud if curious
// connect to the chosen dht nodes
// first curate bootstrap peer list to be only those
// registered with smart contract
var validBootstrapPeers []peer.AddrInfo
if config.PermissionLayer.Permissioned() {
to := 15 * time.Second
validatedBootstrapPeers, _ := config.PermissionLayer.ValidatePeers(bootstrapPeers, to) // w timeout
validBootstrapPeers = validatedBootstrapPeers
} else {
validBootstrapPeers = bootstrapPeers
}
if (len(validBootstrapPeers) == 1) && (len(validBootstrapPeers[0].Addrs) == 0) {
return nil, nil, fmt.Errorf("error makeRoutedHost, the bootstrap set has 0 SC validated nodes")
}
err = bootstrapConnect(ctx, routedHost, validBootstrapPeers)
if err != nil {
return nil, nil, err
}
// Bootstrap the host
err = dht.Bootstrap(ctx)
if err != nil {
return nil, nil, err
}
}
// Build host multiaddress
hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s", routedHost.ID().Pretty()))
// Now we can build a full multiaddress to reach this host
// by encapsulating both addresses:
addrs := routedHost.Addrs()
log.Println("I can be reached at:")
for _, addr := range addrs {
log.Println(addr.Encapsulate(hostAddr))
}
//log.Printf("Now run \"./routed-echo -l %d -d %s%s\" on a different terminal\n", routedHost.ID().Pretty(), config.Global) // FOR DEEP DEBUGGING
return routedHost, dht, nil
}