2018-09-13 13:47:08 +00:00
|
|
|
package p2pd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2018-12-03 13:03:59 +00:00
|
|
|
"fmt"
|
2018-09-13 13:47:08 +00:00
|
|
|
"sync"
|
|
|
|
|
|
|
|
logging "github.com/ipfs/go-log"
|
2018-12-11 19:35:02 +00:00
|
|
|
libp2p "github.com/libp2p/go-libp2p"
|
2019-02-07 09:55:20 +00:00
|
|
|
autonat "github.com/libp2p/go-libp2p-autonat-svc"
|
2018-12-11 19:35:02 +00:00
|
|
|
host "github.com/libp2p/go-libp2p-host"
|
|
|
|
dht "github.com/libp2p/go-libp2p-kad-dht"
|
|
|
|
dhtopts "github.com/libp2p/go-libp2p-kad-dht/opts"
|
|
|
|
peer "github.com/libp2p/go-libp2p-peer"
|
2018-09-13 13:47:08 +00:00
|
|
|
proto "github.com/libp2p/go-libp2p-protocol"
|
2018-12-03 09:25:18 +00:00
|
|
|
ps "github.com/libp2p/go-libp2p-pubsub"
|
2019-01-04 19:50:15 +00:00
|
|
|
routing "github.com/libp2p/go-libp2p-routing"
|
2018-09-15 07:33:00 +00:00
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
2018-12-11 19:35:02 +00:00
|
|
|
manet "github.com/multiformats/go-multiaddr-net"
|
2018-09-13 13:47:08 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var log = logging.Logger("p2pd")
|
|
|
|
|
|
|
|
type Daemon struct {
|
|
|
|
ctx context.Context
|
|
|
|
host host.Host
|
2018-12-06 22:16:50 +00:00
|
|
|
listener manet.Listener
|
2018-09-13 13:47:08 +00:00
|
|
|
|
2019-02-07 09:55:20 +00:00
|
|
|
dht *dht.IpfsDHT
|
|
|
|
pubsub *ps.PubSub
|
|
|
|
autonat *autonat.AutoNATService
|
2018-09-30 08:01:00 +00:00
|
|
|
|
2018-09-13 13:47:08 +00:00
|
|
|
mx sync.Mutex
|
2018-12-06 22:16:50 +00:00
|
|
|
// stream handlers: map of protocol.ID to multi-address
|
|
|
|
handlers map[proto.ID]ma.Multiaddr
|
2018-09-13 13:47:08 +00:00
|
|
|
}
|
|
|
|
|
2019-01-04 19:50:15 +00:00
|
|
|
func NewDaemon(ctx context.Context, maddr ma.Multiaddr, dhtEnabled bool, dhtClient bool, opts ...libp2p.Option) (*Daemon, error) {
|
|
|
|
d := &Daemon{
|
2019-02-04 23:31:47 +00:00
|
|
|
ctx: ctx,
|
2019-01-04 19:50:15 +00:00
|
|
|
handlers: make(map[proto.ID]ma.Multiaddr),
|
|
|
|
}
|
|
|
|
|
|
|
|
if dhtEnabled || dhtClient {
|
|
|
|
var dhtOpts []dhtopts.Option
|
|
|
|
if dhtClient {
|
|
|
|
dhtOpts = append(dhtOpts, dhtopts.Client(true))
|
|
|
|
}
|
|
|
|
|
2019-01-04 19:58:59 +00:00
|
|
|
opts = append(opts, libp2p.Routing(d.DHTRoutingFactory(dhtOpts)))
|
2019-01-04 19:50:15 +00:00
|
|
|
}
|
|
|
|
|
2018-09-13 13:47:08 +00:00
|
|
|
h, err := libp2p.New(ctx, opts...)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-01-04 19:50:15 +00:00
|
|
|
d.host = h
|
2018-09-13 13:47:08 +00:00
|
|
|
|
2018-12-06 22:16:50 +00:00
|
|
|
l, err := manet.Listen(maddr)
|
2018-09-13 13:47:08 +00:00
|
|
|
if err != nil {
|
|
|
|
h.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-01-04 19:54:42 +00:00
|
|
|
d.listener = l
|
2018-09-13 13:47:08 +00:00
|
|
|
|
|
|
|
go d.listen()
|
|
|
|
|
|
|
|
return d, nil
|
|
|
|
}
|
|
|
|
|
2019-01-04 19:50:15 +00:00
|
|
|
func (d *Daemon) DHTRoutingFactory(opts []dhtopts.Option) func(host.Host) (routing.PeerRouting, error) {
|
|
|
|
makeRouting := func(h host.Host) (routing.PeerRouting, error) {
|
|
|
|
dhtInst, err := dht.New(d.ctx, h, opts...)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
d.dht = dhtInst
|
|
|
|
return dhtInst, nil
|
2018-09-30 12:13:42 +00:00
|
|
|
}
|
|
|
|
|
2019-01-04 19:50:15 +00:00
|
|
|
return makeRouting
|
2018-09-30 12:13:42 +00:00
|
|
|
}
|
|
|
|
|
2018-12-03 13:03:59 +00:00
|
|
|
func (d *Daemon) EnablePubsub(router string, sign, strict bool) error {
|
|
|
|
var opts []ps.Option
|
|
|
|
|
|
|
|
if sign {
|
|
|
|
opts = append(opts, ps.WithMessageSigning(sign))
|
|
|
|
|
2018-12-03 13:05:19 +00:00
|
|
|
if strict {
|
|
|
|
opts = append(opts, ps.WithStrictSignatureVerification(strict))
|
|
|
|
}
|
2018-12-03 13:03:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch router {
|
|
|
|
case "floodsub":
|
|
|
|
pubsub, err := ps.NewFloodSub(d.ctx, d.host, opts...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
d.pubsub = pubsub
|
|
|
|
return nil
|
|
|
|
|
|
|
|
case "gossipsub":
|
|
|
|
pubsub, err := ps.NewGossipSub(d.ctx, d.host, opts...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
d.pubsub = pubsub
|
|
|
|
return nil
|
|
|
|
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unknown pubsub router: %s", router)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-07 09:55:20 +00:00
|
|
|
func (d *Daemon) EnableAutoNAT(opts ...libp2p.Option) error {
|
|
|
|
svc, err := autonat.NewAutoNATService(d.ctx, d.host, opts...)
|
|
|
|
d.autonat = svc
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-09-15 07:33:00 +00:00
|
|
|
func (d *Daemon) ID() peer.ID {
|
|
|
|
return d.host.ID()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Daemon) Addrs() []ma.Multiaddr {
|
|
|
|
return d.host.Addrs()
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:47:08 +00:00
|
|
|
func (d *Daemon) listen() {
|
|
|
|
for {
|
|
|
|
c, err := d.listener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("error accepting connection: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug("incoming connection")
|
|
|
|
go d.handleConn(c)
|
|
|
|
}
|
|
|
|
}
|