mirror of
https://github.com/libp2p/go-libp2p.git
synced 2025-10-11 11:00:19 +08:00
refactor for transport changes
Also, make the libp2p constructor fully useful. There should now be no need to manually construct a swarm/host.
This commit is contained in:
176
config/config.go
Normal file
176
config/config.go
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
||||||
|
|
||||||
|
logging "github.com/ipfs/go-log"
|
||||||
|
circuit "github.com/libp2p/go-libp2p-circuit"
|
||||||
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
|
ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr"
|
||||||
|
pnet "github.com/libp2p/go-libp2p-interface-pnet"
|
||||||
|
metrics "github.com/libp2p/go-libp2p-metrics"
|
||||||
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
|
swarm "github.com/libp2p/go-libp2p-swarm"
|
||||||
|
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
|
||||||
|
filter "github.com/libp2p/go-maddr-filter"
|
||||||
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
|
)
|
||||||
|
|
||||||
|
var log = logging.Logger("p2p-config")
|
||||||
|
|
||||||
|
// AddrsFactory is a function that takes a set of multiaddrs we're listening on and
|
||||||
|
// returns the set of multiaddrs we should advertise to the network.
|
||||||
|
type AddrsFactory = bhost.AddrsFactory
|
||||||
|
|
||||||
|
// NATManagerC is a NATManager constructor.
|
||||||
|
type NATManagerC func(inet.Network) bhost.NATManager
|
||||||
|
|
||||||
|
// Config describes a set of settings for a libp2p node
|
||||||
|
//
|
||||||
|
// This is *not* a stable interface. Use the options defined in the root
|
||||||
|
// package.
|
||||||
|
type Config struct {
|
||||||
|
PeerKey crypto.PrivKey
|
||||||
|
|
||||||
|
Transports []TptC
|
||||||
|
Muxers []MsMuxC
|
||||||
|
SecurityTransports []MsSecC
|
||||||
|
Insecure bool
|
||||||
|
Protector pnet.Protector
|
||||||
|
|
||||||
|
Relay bool
|
||||||
|
RelayOpts []circuit.RelayOpt
|
||||||
|
|
||||||
|
ListenAddrs []ma.Multiaddr
|
||||||
|
AddrsFactory bhost.AddrsFactory
|
||||||
|
Filters *filter.Filters
|
||||||
|
|
||||||
|
ConnManager ifconnmgr.ConnManager
|
||||||
|
NATManager NATManagerC
|
||||||
|
Peerstore pstore.Peerstore
|
||||||
|
Reporter metrics.Reporter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNode constructs a new libp2p Host from the Config.
|
||||||
|
//
|
||||||
|
// This function consumes the config. Do not reuse it (really!).
|
||||||
|
func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) {
|
||||||
|
// Check this early. Prevents us from even *starting* without verifying this.
|
||||||
|
if pnet.ForcePrivateNetwork && cfg.Protector == nil {
|
||||||
|
log.Error("tried to create a libp2p node with no Private" +
|
||||||
|
" Network Protector but usage of Private Networks" +
|
||||||
|
" is forced by the enviroment")
|
||||||
|
// Note: This is *also* checked the upgrader itself so it'll be
|
||||||
|
// enforced even *if* you don't use the libp2p constructor.
|
||||||
|
return nil, pnet.ErrNotInPrivateNetwork
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.PeerKey == nil {
|
||||||
|
return nil, fmt.Errorf("no peer key specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain Peer ID from public key
|
||||||
|
pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Peerstore == nil {
|
||||||
|
return nil, fmt.Errorf("no peerstore specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cfg.Insecure {
|
||||||
|
cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey)
|
||||||
|
cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make the swarm implementation configurable.
|
||||||
|
swrm := swarm.NewSwarm(ctx, pid, cfg.Peerstore, cfg.Reporter)
|
||||||
|
if cfg.Filters != nil {
|
||||||
|
swrm.Filters = cfg.Filters
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make host implementation configurable.
|
||||||
|
h, err := bhost.NewHost(ctx, swrm, &bhost.HostOpts{
|
||||||
|
ConnManager: cfg.ConnManager,
|
||||||
|
AddrsFactory: cfg.AddrsFactory,
|
||||||
|
NATManager: cfg.NATManager,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
swrm.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
upgrader := new(tptu.Upgrader)
|
||||||
|
upgrader.Protector = cfg.Protector
|
||||||
|
upgrader.Filters = swrm.Filters
|
||||||
|
if cfg.Insecure {
|
||||||
|
upgrader.Secure = makeInsecureTransport(pid)
|
||||||
|
} else {
|
||||||
|
upgrader.Secure, err = makeSecurityTransport(h, cfg.SecurityTransports)
|
||||||
|
if err != nil {
|
||||||
|
h.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
upgrader.Muxer, err = makeMuxer(h, cfg.Muxers)
|
||||||
|
if err != nil {
|
||||||
|
h.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tpts, err := makeTransports(h, upgrader, cfg.Transports)
|
||||||
|
if err != nil {
|
||||||
|
h.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, t := range tpts {
|
||||||
|
err = swrm.AddTransport(t)
|
||||||
|
if err != nil {
|
||||||
|
h.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Relay {
|
||||||
|
err := circuit.AddRelayTransport(swrm.Context(), h, upgrader, cfg.RelayOpts...)
|
||||||
|
if err != nil {
|
||||||
|
h.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This method succeeds if listening on one address succeeds. We
|
||||||
|
// should probably fail if listening on *any* addr fails.
|
||||||
|
if err := h.Network().Listen(cfg.ListenAddrs...); err != nil {
|
||||||
|
h.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Configure routing (it's a pain to setup).
|
||||||
|
// TODO: Bootstrapping.
|
||||||
|
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option is a libp2p config option that can be given to the libp2p constructor
|
||||||
|
// (`libp2p.New`).
|
||||||
|
type Option func(cfg *Config) error
|
||||||
|
|
||||||
|
// Apply applies the given options to the config, returning the first error
|
||||||
|
// encountered (if any).
|
||||||
|
func (cfg *Config) Apply(opts ...Option) error {
|
||||||
|
for _, opt := range opts {
|
||||||
|
if err := opt(cfg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
62
config/constructor_types.go
Normal file
62
config/constructor_types.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
security "github.com/libp2p/go-conn-security"
|
||||||
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
|
pnet "github.com/libp2p/go-libp2p-interface-pnet"
|
||||||
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
|
transport "github.com/libp2p/go-libp2p-transport"
|
||||||
|
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
|
||||||
|
filter "github.com/libp2p/go-maddr-filter"
|
||||||
|
mux "github.com/libp2p/go-stream-muxer"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// interfaces
|
||||||
|
hostType = reflect.TypeOf((*host.Host)(nil)).Elem()
|
||||||
|
networkType = reflect.TypeOf((*inet.Network)(nil)).Elem()
|
||||||
|
transportType = reflect.TypeOf((*transport.Transport)(nil)).Elem()
|
||||||
|
muxType = reflect.TypeOf((*mux.Transport)(nil)).Elem()
|
||||||
|
securityType = reflect.TypeOf((*security.Transport)(nil)).Elem()
|
||||||
|
protectorType = reflect.TypeOf((*pnet.Protector)(nil)).Elem()
|
||||||
|
privKeyType = reflect.TypeOf((*crypto.PrivKey)(nil)).Elem()
|
||||||
|
pubKeyType = reflect.TypeOf((*crypto.PubKey)(nil)).Elem()
|
||||||
|
pstoreType = reflect.TypeOf((*pstore.Peerstore)(nil)).Elem()
|
||||||
|
|
||||||
|
// concrete types
|
||||||
|
peerIDType = reflect.TypeOf((peer.ID)(""))
|
||||||
|
filtersType = reflect.TypeOf((*filter.Filters)(nil))
|
||||||
|
upgraderType = reflect.TypeOf((*tptu.Upgrader)(nil))
|
||||||
|
)
|
||||||
|
|
||||||
|
var argTypes = map[reflect.Type]constructor{
|
||||||
|
upgraderType: func(h host.Host, u *tptu.Upgrader) interface{} { return u },
|
||||||
|
hostType: func(h host.Host, u *tptu.Upgrader) interface{} { return h },
|
||||||
|
networkType: func(h host.Host, u *tptu.Upgrader) interface{} { return h.Network() },
|
||||||
|
muxType: func(h host.Host, u *tptu.Upgrader) interface{} { return u.Muxer },
|
||||||
|
securityType: func(h host.Host, u *tptu.Upgrader) interface{} { return u.Secure },
|
||||||
|
protectorType: func(h host.Host, u *tptu.Upgrader) interface{} { return u.Protector },
|
||||||
|
filtersType: func(h host.Host, u *tptu.Upgrader) interface{} { return u.Filters },
|
||||||
|
peerIDType: func(h host.Host, u *tptu.Upgrader) interface{} { return h.ID() },
|
||||||
|
privKeyType: func(h host.Host, u *tptu.Upgrader) interface{} { return h.Peerstore().PrivKey(h.ID()) },
|
||||||
|
pubKeyType: func(h host.Host, u *tptu.Upgrader) interface{} { return h.Peerstore().PubKey(h.ID()) },
|
||||||
|
pstoreType: func(h host.Host, u *tptu.Upgrader) interface{} { return h.Peerstore() },
|
||||||
|
}
|
||||||
|
|
||||||
|
func newArgTypeSet(types ...reflect.Type) map[reflect.Type]constructor {
|
||||||
|
result := make(map[reflect.Type]constructor, len(types))
|
||||||
|
for _, ty := range types {
|
||||||
|
c, ok := argTypes[ty]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("missing constructor for type %s", ty))
|
||||||
|
}
|
||||||
|
result[ty] = c
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
62
config/muxer.go
Normal file
62
config/muxer.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
|
mux "github.com/libp2p/go-stream-muxer"
|
||||||
|
msmux "github.com/whyrusleeping/go-smux-multistream"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MuxC is a stream multiplex transport constructor
|
||||||
|
type MuxC func(h host.Host) (mux.Transport, error)
|
||||||
|
|
||||||
|
// MsMuxC is a tuple containing a multiplex transport constructor and a protocol
|
||||||
|
// ID.
|
||||||
|
type MsMuxC struct {
|
||||||
|
MuxC
|
||||||
|
ID string
|
||||||
|
}
|
||||||
|
|
||||||
|
var muxArgTypes = newArgTypeSet(hostType, networkType, peerIDType, pstoreType)
|
||||||
|
|
||||||
|
// MuxerConstructor creates a multiplex constructor from the passed parameter
|
||||||
|
// using reflection.
|
||||||
|
func MuxerConstructor(m interface{}) (MuxC, error) {
|
||||||
|
// Already constructed?
|
||||||
|
if t, ok := m.(mux.Transport); ok {
|
||||||
|
return func(_ host.Host) (mux.Transport, error) {
|
||||||
|
return t, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctor, err := makeConstructor(m, muxType, muxArgTypes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return func(h host.Host) (mux.Transport, error) {
|
||||||
|
t, err := ctor(h, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t.(mux.Transport), nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeMuxer(h host.Host, tpts []MsMuxC) (mux.Transport, error) {
|
||||||
|
muxMuxer := msmux.NewBlankTransport()
|
||||||
|
transportSet := make(map[string]struct{}, len(tpts))
|
||||||
|
for _, tptC := range tpts {
|
||||||
|
if _, ok := transportSet[tptC.ID]; ok {
|
||||||
|
return nil, fmt.Errorf("duplicate muxer transport: %s", tptC.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, tptC := range tpts {
|
||||||
|
tpt, err := tptC.MuxC(h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
muxMuxer.AddTransport(tptC.ID, tpt)
|
||||||
|
}
|
||||||
|
return muxMuxer, nil
|
||||||
|
}
|
54
config/muxer_test.go
Normal file
54
config/muxer_test.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
|
mux "github.com/libp2p/go-stream-muxer"
|
||||||
|
yamux "github.com/whyrusleeping/go-smux-yamux"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMuxerSimple(t *testing.T) {
|
||||||
|
// single
|
||||||
|
_, err := MuxerConstructor(func(_ peer.ID) mux.Transport { return nil })
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMuxerByValue(t *testing.T) {
|
||||||
|
_, err := MuxerConstructor(yamux.DefaultTransport)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestMuxerDuplicate(t *testing.T) {
|
||||||
|
_, err := MuxerConstructor(func(_ peer.ID, _ peer.ID) mux.Transport { return nil })
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMuxerError(t *testing.T) {
|
||||||
|
_, err := MuxerConstructor(func() (mux.Transport, error) { return nil, nil })
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMuxerBadTypes(t *testing.T) {
|
||||||
|
for i, f := range []interface{}{
|
||||||
|
func() error { return nil },
|
||||||
|
func() string { return "" },
|
||||||
|
func() {},
|
||||||
|
func(string) mux.Transport { return nil },
|
||||||
|
func(string) (mux.Transport, error) { return nil, nil },
|
||||||
|
nil,
|
||||||
|
"testing",
|
||||||
|
} {
|
||||||
|
|
||||||
|
if _, err := MuxerConstructor(f); err == nil {
|
||||||
|
t.Fatalf("constructor %d with type %T should have failed", i, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
config/reflection_magic.go
Normal file
126
config/reflection_magic.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
|
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
|
|
||||||
|
// checks if a function returns either the specified type or the specified type
|
||||||
|
// and an error.
|
||||||
|
func checkReturnType(fnType, tptType reflect.Type) error {
|
||||||
|
switch fnType.NumOut() {
|
||||||
|
case 2:
|
||||||
|
if fnType.Out(1) != errorType {
|
||||||
|
return fmt.Errorf("expected (optional) second return value from transport constructor to be an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fallthrough
|
||||||
|
case 1:
|
||||||
|
if !fnType.Out(0).Implements(tptType) {
|
||||||
|
return fmt.Errorf("expected first return value from transport constructor to be a transport")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("expected transport constructor to return a transport and, optionally, an error")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles return values with optional errors. That is, return values of the
|
||||||
|
// form `(something, error)` or just `something`.
|
||||||
|
//
|
||||||
|
// Panics if the return value isn't of the correct form.
|
||||||
|
func handleReturnValue(out []reflect.Value) (interface{}, error) {
|
||||||
|
switch len(out) {
|
||||||
|
case 2:
|
||||||
|
err := out[1]
|
||||||
|
if err != (reflect.Value{}) && !err.IsNil() {
|
||||||
|
return nil, err.Interface().(error)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 1:
|
||||||
|
tpt := out[0]
|
||||||
|
|
||||||
|
// Check for nil value and nil error.
|
||||||
|
if tpt == (reflect.Value{}) {
|
||||||
|
return nil, fmt.Errorf("unspecified error")
|
||||||
|
}
|
||||||
|
switch tpt.Kind() {
|
||||||
|
case reflect.Ptr, reflect.Interface, reflect.Func:
|
||||||
|
if tpt.IsNil() {
|
||||||
|
return nil, fmt.Errorf("unspecified error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tpt.Interface(), nil
|
||||||
|
default:
|
||||||
|
panic("expected 1 or 2 return values from transport constructor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calls the transport constructor and annotates the error with the name of the constructor.
|
||||||
|
func callConstructor(c reflect.Value, args []reflect.Value) (interface{}, error) {
|
||||||
|
val, err := handleReturnValue(c.Call(args))
|
||||||
|
if err != nil {
|
||||||
|
name := runtime.FuncForPC(c.Pointer()).Name()
|
||||||
|
if name != "" {
|
||||||
|
// makes debugging easier
|
||||||
|
return nil, fmt.Errorf("transport constructor %s failed: %s", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type constructor func(h host.Host, u *tptu.Upgrader) interface{}
|
||||||
|
|
||||||
|
func makeArgumentConstructors(fnType reflect.Type, argTypes map[reflect.Type]constructor) ([]constructor, error) {
|
||||||
|
out := make([]constructor, fnType.NumIn())
|
||||||
|
for i := range out {
|
||||||
|
argType := fnType.In(i)
|
||||||
|
c, ok := argTypes[argType]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("argument %d has an unexpected type %s", i, argType.Name())
|
||||||
|
}
|
||||||
|
out[i] = c
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// makes a transport constructor.
|
||||||
|
func makeConstructor(
|
||||||
|
tpt interface{},
|
||||||
|
tptType reflect.Type,
|
||||||
|
argTypes map[reflect.Type]constructor,
|
||||||
|
) (func(host.Host, *tptu.Upgrader) (interface{}, error), error) {
|
||||||
|
v := reflect.ValueOf(tpt)
|
||||||
|
// avoid panicing on nil/zero value.
|
||||||
|
if v == (reflect.Value{}) {
|
||||||
|
return nil, fmt.Errorf("expected a transport or transport constructor, got a %T", tpt)
|
||||||
|
}
|
||||||
|
t := v.Type()
|
||||||
|
if t.Kind() != reflect.Func {
|
||||||
|
return nil, fmt.Errorf("expected a transport or transport constructor, got a %T", tpt)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkReturnType(t, tptType); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
argConstructors, err := makeArgumentConstructors(t, argTypes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(h host.Host, u *tptu.Upgrader) (interface{}, error) {
|
||||||
|
arguments := make([]reflect.Value, len(argConstructors))
|
||||||
|
for i, makeArg := range argConstructors {
|
||||||
|
arguments[i] = reflect.ValueOf(makeArg(h, u))
|
||||||
|
}
|
||||||
|
return callConstructor(v, arguments)
|
||||||
|
}, nil
|
||||||
|
}
|
142
config/reflection_magic_test.go
Normal file
142
config/reflection_magic_test.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHandleReturnValue(t *testing.T) {
|
||||||
|
// one value
|
||||||
|
v, err := handleReturnValue([]reflect.Value{reflect.ValueOf(1)})
|
||||||
|
if v.(int) != 1 {
|
||||||
|
t.Fatal("expected value")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nil value
|
||||||
|
v, err = handleReturnValue([]reflect.Value{reflect.ValueOf(nil)})
|
||||||
|
if v != nil {
|
||||||
|
t.Fatal("expected no value")
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nil value, nil err
|
||||||
|
v, err = handleReturnValue([]reflect.Value{reflect.ValueOf(nil), reflect.ValueOf(nil)})
|
||||||
|
if v != nil {
|
||||||
|
t.Fatal("expected no value")
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// two values
|
||||||
|
v, err = handleReturnValue([]reflect.Value{reflect.ValueOf(1), reflect.ValueOf(nil)})
|
||||||
|
if v, ok := v.(int); !ok || v != 1 {
|
||||||
|
t.Fatalf("expected value of 1, got %v", v)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// an error
|
||||||
|
myError := errors.New("my error")
|
||||||
|
_, err = handleReturnValue([]reflect.Value{reflect.ValueOf(1), reflect.ValueOf(myError)})
|
||||||
|
if err != myError {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, vals := range [][]reflect.Value{
|
||||||
|
{reflect.ValueOf(1), reflect.ValueOf("not an error")},
|
||||||
|
{},
|
||||||
|
{reflect.ValueOf(1), reflect.ValueOf(myError), reflect.ValueOf(myError)},
|
||||||
|
} {
|
||||||
|
func() {
|
||||||
|
defer func() { recover() }()
|
||||||
|
handleReturnValue(vals)
|
||||||
|
t.Fatal("expected a panic")
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type foo interface {
|
||||||
|
foo() foo
|
||||||
|
}
|
||||||
|
|
||||||
|
var fooType = reflect.TypeOf((*foo)(nil)).Elem()
|
||||||
|
|
||||||
|
func TestCheckReturnType(t *testing.T) {
|
||||||
|
for i, fn := range []interface{}{
|
||||||
|
func() { panic("") },
|
||||||
|
func() error { panic("") },
|
||||||
|
func() (error, error) { panic("") },
|
||||||
|
func() (foo, error, error) { panic("") },
|
||||||
|
func() (foo, foo) { panic("") },
|
||||||
|
} {
|
||||||
|
if checkReturnType(reflect.TypeOf(fn), fooType) == nil {
|
||||||
|
t.Errorf("expected falure for case %d (type %T)", i, fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, fn := range []interface{}{
|
||||||
|
func() foo { panic("") },
|
||||||
|
func() (foo, error) { panic("") },
|
||||||
|
} {
|
||||||
|
if err := checkReturnType(reflect.TypeOf(fn), fooType); err != nil {
|
||||||
|
t.Errorf("expected success for case %d (type %T), got: %s", i, fn, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func constructFoo() foo {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type fooImpl struct{}
|
||||||
|
|
||||||
|
func (f *fooImpl) foo() foo { return nil }
|
||||||
|
|
||||||
|
func TestCallConstructor(t *testing.T) {
|
||||||
|
_, err := callConstructor(reflect.ValueOf(constructFoo), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected constructor to fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(err.Error(), "constructFoo") {
|
||||||
|
t.Errorf("expected error to contain the constructor name: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := callConstructor(reflect.ValueOf(func() foo { return &fooImpl{} }), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, ok := v.(*fooImpl); !ok {
|
||||||
|
t.Fatal("expected a fooImpl")
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err = callConstructor(reflect.ValueOf(func() *fooImpl { return new(fooImpl) }), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, ok := v.(*fooImpl); !ok {
|
||||||
|
t.Fatal("expected a fooImpl")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = callConstructor(reflect.ValueOf(func() (*fooImpl, error) { return nil, nil }), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error")
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err = callConstructor(reflect.ValueOf(func() (*fooImpl, error) { return new(fooImpl), nil }), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, ok := v.(*fooImpl); !ok {
|
||||||
|
t.Fatal("expected a fooImpl")
|
||||||
|
}
|
||||||
|
}
|
76
config/security.go
Normal file
76
config/security.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
security "github.com/libp2p/go-conn-security"
|
||||||
|
csms "github.com/libp2p/go-conn-security-multistream"
|
||||||
|
insecure "github.com/libp2p/go-conn-security/insecure"
|
||||||
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SecC is a security transport constructor
|
||||||
|
type SecC func(h host.Host) (security.Transport, error)
|
||||||
|
|
||||||
|
// MsSecC is a tuple containing a security transport constructor and a protocol
|
||||||
|
// ID.
|
||||||
|
type MsSecC struct {
|
||||||
|
SecC
|
||||||
|
ID string
|
||||||
|
}
|
||||||
|
|
||||||
|
var securityArgTypes = newArgTypeSet(
|
||||||
|
hostType, networkType, peerIDType,
|
||||||
|
privKeyType, pubKeyType, pstoreType,
|
||||||
|
)
|
||||||
|
|
||||||
|
// SecurityConstructor creates a security constructor from the passed parameter
|
||||||
|
// using reflection.
|
||||||
|
func SecurityConstructor(sec interface{}) (SecC, error) {
|
||||||
|
// Already constructed?
|
||||||
|
if t, ok := sec.(security.Transport); ok {
|
||||||
|
return func(_ host.Host) (security.Transport, error) {
|
||||||
|
return t, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctor, err := makeConstructor(sec, securityType, securityArgTypes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return func(h host.Host) (security.Transport, error) {
|
||||||
|
t, err := ctor(h, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t.(security.Transport), nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeInsecureTransport(id peer.ID) security.Transport {
|
||||||
|
secMuxer := new(csms.SSMuxer)
|
||||||
|
secMuxer.AddTransport(insecure.ID, insecure.New(id))
|
||||||
|
return secMuxer
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSecurityTransport(h host.Host, tpts []MsSecC) (security.Transport, error) {
|
||||||
|
secMuxer := new(csms.SSMuxer)
|
||||||
|
transportSet := make(map[string]struct{}, len(tpts))
|
||||||
|
for _, tptC := range tpts {
|
||||||
|
if _, ok := transportSet[tptC.ID]; ok {
|
||||||
|
return nil, fmt.Errorf("duplicate security transport: %s", tptC.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, tptC := range tpts {
|
||||||
|
tpt, err := tptC.SecC(h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, ok := tpt.(*insecure.Transport); ok {
|
||||||
|
return nil, fmt.Errorf("cannot construct libp2p with an insecure transport, set the Insecure config option instead")
|
||||||
|
}
|
||||||
|
secMuxer.AddTransport(tptC.ID, tpt)
|
||||||
|
}
|
||||||
|
return secMuxer, nil
|
||||||
|
}
|
66
config/transport.go
Normal file
66
config/transport.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
|
transport "github.com/libp2p/go-libp2p-transport"
|
||||||
|
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TptC is the type for libp2p transport constructors. You probably won't ever
|
||||||
|
// implement this function interface directly. Instead, pass your transport
|
||||||
|
// constructor to TransportConstructor.
|
||||||
|
type TptC func(h host.Host, u *tptu.Upgrader) (transport.Transport, error)
|
||||||
|
|
||||||
|
var transportArgTypes = argTypes
|
||||||
|
|
||||||
|
// TransportConstructor uses reflection to turn a function that constructs a
|
||||||
|
// transport into a TptC.
|
||||||
|
//
|
||||||
|
// You can pass either a constructed transport (something that implements
|
||||||
|
// `transport.Transport`) or a function that takes any of:
|
||||||
|
//
|
||||||
|
// * The local peer ID.
|
||||||
|
// * A transport connection upgrader.
|
||||||
|
// * A private key.
|
||||||
|
// * A public key.
|
||||||
|
// * A Host.
|
||||||
|
// * A Network.
|
||||||
|
// * A Peerstore.
|
||||||
|
// * An address filter.
|
||||||
|
// * A security transport.
|
||||||
|
// * A stream multiplexer transport.
|
||||||
|
// * A private network protector.
|
||||||
|
//
|
||||||
|
// And returns a type implementing transport.Transport and, optionally, an error
|
||||||
|
// (as the second argument).
|
||||||
|
func TransportConstructor(tpt interface{}) (TptC, error) {
|
||||||
|
// Already constructed?
|
||||||
|
if t, ok := tpt.(transport.Transport); ok {
|
||||||
|
return func(_ host.Host, _ *tptu.Upgrader) (transport.Transport, error) {
|
||||||
|
return t, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
ctor, err := makeConstructor(tpt, transportType, transportArgTypes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return func(h host.Host, u *tptu.Upgrader) (transport.Transport, error) {
|
||||||
|
t, err := ctor(h, u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t.(transport.Transport), nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTransports(h host.Host, u *tptu.Upgrader, tpts []TptC) ([]transport.Transport, error) {
|
||||||
|
transports := make([]transport.Transport, len(tpts))
|
||||||
|
for i, tC := range tpts {
|
||||||
|
t, err := tC(h, u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
transports[i] = t
|
||||||
|
}
|
||||||
|
return transports, nil
|
||||||
|
}
|
109
defaults.go
Normal file
109
defaults.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package libp2p
|
||||||
|
|
||||||
|
// This file contains all the default configuration options.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
|
||||||
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
|
secio "github.com/libp2p/go-libp2p-secio"
|
||||||
|
tcp "github.com/libp2p/go-tcp-transport"
|
||||||
|
ws "github.com/libp2p/go-ws-transport"
|
||||||
|
mplex "github.com/whyrusleeping/go-smux-multiplex"
|
||||||
|
yamux "github.com/whyrusleeping/go-smux-yamux"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultSecurity is the default security option.
|
||||||
|
//
|
||||||
|
// Useful when you want to extend, but not replace, the supported transport
|
||||||
|
// security protocols.
|
||||||
|
var DefaultSecurity = Security(secio.ID, secio.New)
|
||||||
|
|
||||||
|
// DefaultMuxer configures libp2p to use the stream connection multiplexers.
|
||||||
|
//
|
||||||
|
// Use this option when you want to *extend* the set of multiplexers used by
|
||||||
|
// libp2p instead of replacing them.
|
||||||
|
var DefaultMuxers = ChainOptions(
|
||||||
|
Muxer("/yamux/1.0.0", yamux.DefaultTransport),
|
||||||
|
Muxer("/mplex/6.3.0", mplex.DefaultTransport),
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultTransports are the default libp2p transports.
|
||||||
|
//
|
||||||
|
// Use this option when you want to *extend* the set of multiplexers used by
|
||||||
|
// libp2p instead of replacing them.
|
||||||
|
var DefaultTransports = ChainOptions(
|
||||||
|
Transport(tcp.NewTCPTransport),
|
||||||
|
Transport(ws.New),
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultPeerstore configures libp2p to use the default peerstore.
|
||||||
|
var DefaultPeerstore Option = func(cfg *Config) error {
|
||||||
|
return cfg.Apply(Peerstore(pstore.NewPeerstore()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomIdentity generates a random identity (default behaviour)
|
||||||
|
var RandomIdentity = func(cfg *Config) error {
|
||||||
|
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return cfg.Apply(Identity(priv))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete list of default options and when to fallback on them.
|
||||||
|
//
|
||||||
|
// Please *DON'T* specify default options any other way. Putting this all here
|
||||||
|
// makes tracking defaults *much* easier.
|
||||||
|
var defaults = []struct {
|
||||||
|
fallback func(cfg *Config) bool
|
||||||
|
opt Option
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fallback: func(cfg *Config) bool { return cfg.Transports == nil },
|
||||||
|
opt: DefaultTransports,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fallback: func(cfg *Config) bool { return cfg.Muxers == nil },
|
||||||
|
opt: DefaultMuxers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fallback: func(cfg *Config) bool { return !cfg.Insecure && cfg.SecurityTransports == nil },
|
||||||
|
opt: DefaultSecurity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fallback: func(cfg *Config) bool { return cfg.PeerKey == nil },
|
||||||
|
opt: RandomIdentity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fallback: func(cfg *Config) bool { return cfg.Peerstore == nil },
|
||||||
|
opt: DefaultPeerstore,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defaults configures libp2p to use the default options. Can be combined with
|
||||||
|
// other options to *extend* the default options.
|
||||||
|
var Defaults Option = func(cfg *Config) error {
|
||||||
|
for _, def := range defaults {
|
||||||
|
if err := cfg.Apply(def.opt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FallbackDefaults applies default options to the libp2p node if and only if no
|
||||||
|
// other relevent options have been applied. will be appended to the options
|
||||||
|
// passed into New.
|
||||||
|
var FallbackDefaults Option = func(cfg *Config) error {
|
||||||
|
for _, def := range defaults {
|
||||||
|
if !def.fallback(cfg) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := cfg.Apply(def.opt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
17
error_util.go
Normal file
17
error_util.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package libp2p
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func traceError(err error, skip int) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, file, line, ok := runtime.Caller(skip + 1)
|
||||||
|
if !ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s:%d: %s", file, line, err)
|
||||||
|
}
|
@@ -39,13 +39,13 @@ import (
|
|||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/libp2p/go-libp2p"
|
||||||
|
|
||||||
"github.com/libp2p/go-libp2p-crypto"
|
"github.com/libp2p/go-libp2p-crypto"
|
||||||
"github.com/libp2p/go-libp2p-host"
|
"github.com/libp2p/go-libp2p-host"
|
||||||
"github.com/libp2p/go-libp2p-net"
|
"github.com/libp2p/go-libp2p-net"
|
||||||
"github.com/libp2p/go-libp2p-peer"
|
"github.com/libp2p/go-libp2p-peer"
|
||||||
"github.com/libp2p/go-libp2p-peerstore"
|
"github.com/libp2p/go-libp2p-peerstore"
|
||||||
"github.com/libp2p/go-libp2p-swarm"
|
|
||||||
"github.com/libp2p/go-libp2p/p2p/host/basic"
|
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -155,37 +155,27 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new RSA key pair for this host
|
// Creates a new RSA key pair for this host
|
||||||
prvKey, pubKey, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r)
|
prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getting host ID from public key.
|
|
||||||
// host ID is the hash of public key
|
|
||||||
nodeID, _ := peer.IDFromPublicKey(pubKey)
|
|
||||||
|
|
||||||
// 0.0.0.0 will listen on any interface device
|
// 0.0.0.0 will listen on any interface device
|
||||||
sourceMultiAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *sourcePort))
|
sourceMultiAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *sourcePort))
|
||||||
|
|
||||||
// Adding self to the peerstore.
|
// libp2p.New constructs a new libp2p Host.
|
||||||
ps := peerstore.NewPeerstore()
|
// Other options can be added here.
|
||||||
ps.AddPrivKey(nodeID, prvKey)
|
host, err := libp2p.New(
|
||||||
ps.AddPubKey(nodeID, pubKey)
|
context.Background(),
|
||||||
|
libp2p.ListenAddrs(sourceMultiAddr),
|
||||||
// Creating a new Swarm network.
|
libp2p.Identity(prvKey),
|
||||||
network, err := swarm.NewNetwork(context.Background(), []multiaddr.Multiaddr{sourceMultiAddr}, nodeID, ps, nil)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHost constructs a new *BasicHost and activates it by attaching its
|
|
||||||
// stream and connection handlers to the given inet.Network (network).
|
|
||||||
// Other options like NATManager can also be added here.
|
|
||||||
// See docs: https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#HostOpts
|
|
||||||
host := basichost.New(network)
|
|
||||||
|
|
||||||
if *dest == "" {
|
if *dest == "" {
|
||||||
// Set a function as stream handler.
|
// Set a function as stream handler.
|
||||||
// This function is called when a peer initiate a connection and starts a stream with this peer.
|
// This function is called when a peer initiate a connection and starts a stream with this peer.
|
||||||
|
@@ -49,7 +49,7 @@ func makeBasicHost(listenPort int, secio bool, randseed int64) (host.Host, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !secio {
|
if !secio {
|
||||||
opts = append(opts, libp2p.NoEncryption())
|
opts = append(opts, libp2p.NoSecurity)
|
||||||
}
|
}
|
||||||
|
|
||||||
basicHost, err := libp2p.New(context.Background(), opts...)
|
basicHost, err := libp2p.New(context.Background(), opts...)
|
||||||
|
@@ -12,16 +12,14 @@ import (
|
|||||||
|
|
||||||
// We need to import libp2p's libraries that we use in this project.
|
// We need to import libp2p's libraries that we use in this project.
|
||||||
// In order to work, these libraries need to be rewritten by gx-go.
|
// In order to work, these libraries need to be rewritten by gx-go.
|
||||||
crypto "github.com/libp2p/go-libp2p-crypto"
|
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
ps "github.com/libp2p/go-libp2p-peerstore"
|
ps "github.com/libp2p/go-libp2p-peerstore"
|
||||||
swarm "github.com/libp2p/go-libp2p-swarm"
|
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
manet "github.com/multiformats/go-multiaddr-net"
|
manet "github.com/multiformats/go-multiaddr-net"
|
||||||
|
|
||||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
libp2p "github.com/libp2p/go-libp2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Protocol defines the libp2p protocol that we will use for the libp2p proxy
|
// Protocol defines the libp2p protocol that we will use for the libp2p proxy
|
||||||
@@ -33,27 +31,11 @@ const Protocol = "/proxy-example/0.0.1"
|
|||||||
// makeRandomHost creates a libp2p host with a randomly generated identity.
|
// makeRandomHost creates a libp2p host with a randomly generated identity.
|
||||||
// This step is described in depth in other tutorials.
|
// This step is described in depth in other tutorials.
|
||||||
func makeRandomHost(port int) host.Host {
|
func makeRandomHost(port int) host.Host {
|
||||||
priv, pub, err := crypto.GenerateKeyPair(crypto.RSA, 2048)
|
host, err := libp2p.New(context.Background(), libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
pid, err := peer.IDFromPublicKey(pub)
|
return host
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
listen, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
ps := ps.NewPeerstore()
|
|
||||||
ps.AddPrivKey(pid, priv)
|
|
||||||
ps.AddPubKey(pid, pub)
|
|
||||||
n, err := swarm.NewNetwork(context.Background(),
|
|
||||||
[]ma.Multiaddr{listen}, pid, ps, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
return bhost.New(n)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyService provides HTTP proxying on top of libp2p by launching an
|
// ProxyService provides HTTP proxying on top of libp2p by launching an
|
||||||
|
@@ -6,11 +6,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
|
libp2p "github.com/libp2p/go-libp2p"
|
||||||
crypto "github.com/libp2p/go-libp2p-crypto"
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
|
||||||
ps "github.com/libp2p/go-libp2p-peerstore"
|
ps "github.com/libp2p/go-libp2p-peerstore"
|
||||||
swarm "github.com/libp2p/go-libp2p-swarm"
|
|
||||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,14 +16,13 @@ import (
|
|||||||
func makeRandomNode(port int, done chan bool) *Node {
|
func makeRandomNode(port int, done chan bool) *Node {
|
||||||
// Ignoring most errors for brevity
|
// Ignoring most errors for brevity
|
||||||
// See echo example for more details and better implementation
|
// See echo example for more details and better implementation
|
||||||
priv, pub, _ := crypto.GenerateKeyPair(crypto.Secp256k1, 256)
|
priv, _, _ := crypto.GenerateKeyPair(crypto.Secp256k1, 256)
|
||||||
pid, _ := peer.IDFromPublicKey(pub)
|
|
||||||
listen, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port))
|
listen, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port))
|
||||||
peerStore := ps.NewPeerstore()
|
host, _ := libp2p.New(
|
||||||
peerStore.AddPrivKey(pid, priv)
|
context.Background(),
|
||||||
peerStore.AddPubKey(pid, pub)
|
libp2p.ListenAddrs(listen),
|
||||||
n, _ := swarm.NewNetwork(context.Background(), []ma.Multiaddr{listen}, pid, peerStore, nil)
|
libp2p.Identity(priv),
|
||||||
host := bhost.New(n)
|
)
|
||||||
|
|
||||||
return NewNode(host, done)
|
return NewNode(host, done)
|
||||||
}
|
}
|
||||||
|
@@ -8,15 +8,11 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
crypto "github.com/libp2p/go-libp2p-crypto"
|
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
|
||||||
ps "github.com/libp2p/go-libp2p-peerstore"
|
ps "github.com/libp2p/go-libp2p-peerstore"
|
||||||
swarm "github.com/libp2p/go-libp2p-swarm"
|
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
|
||||||
|
|
||||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
libp2p "github.com/libp2p/go-libp2p"
|
||||||
multicodec "github.com/multiformats/go-multicodec"
|
multicodec "github.com/multiformats/go-multicodec"
|
||||||
json "github.com/multiformats/go-multicodec/json"
|
json "github.com/multiformats/go-multicodec/json"
|
||||||
)
|
)
|
||||||
@@ -80,17 +76,11 @@ var conversationMsgs = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeRandomHost(port int) host.Host {
|
func makeRandomHost(port int) host.Host {
|
||||||
// Ignoring most errors for brevity
|
h, err := libp2p.New(context.Background(), libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port)))
|
||||||
// See echo example for more details and better implementation
|
if err != nil {
|
||||||
priv, pub, _ := crypto.GenerateKeyPair(crypto.RSA, 2048)
|
panic(err)
|
||||||
pid, _ := peer.IDFromPublicKey(pub)
|
}
|
||||||
listen, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port))
|
return h
|
||||||
ps := ps.NewPeerstore()
|
|
||||||
ps.AddPrivKey(pid, priv)
|
|
||||||
ps.AddPubKey(pid, pub)
|
|
||||||
n, _ := swarm.NewNetwork(context.Background(),
|
|
||||||
[]ma.Multiaddr{listen}, pid, ps, nil)
|
|
||||||
return bhost.New(n)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
243
libp2p.go
243
libp2p.go
@@ -2,240 +2,49 @@ package libp2p
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
crypto "github.com/libp2p/go-libp2p-crypto"
|
config "github.com/libp2p/go-libp2p/config"
|
||||||
|
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
pnet "github.com/libp2p/go-libp2p-interface-pnet"
|
|
||||||
metrics "github.com/libp2p/go-libp2p-metrics"
|
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
|
||||||
swarm "github.com/libp2p/go-libp2p-swarm"
|
|
||||||
transport "github.com/libp2p/go-libp2p-transport"
|
|
||||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
|
||||||
mux "github.com/libp2p/go-stream-muxer"
|
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
|
||||||
mplex "github.com/whyrusleeping/go-smux-multiplex"
|
|
||||||
msmux "github.com/whyrusleeping/go-smux-multistream"
|
|
||||||
yamux "github.com/whyrusleeping/go-smux-yamux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config describes a set of settings for a libp2p node
|
// Config describes a set of settings for a libp2p node
|
||||||
type Config struct {
|
type Config = config.Config
|
||||||
Transports []transport.Transport
|
|
||||||
Muxer mux.Transport
|
|
||||||
ListenAddrs []ma.Multiaddr
|
|
||||||
PeerKey crypto.PrivKey
|
|
||||||
Peerstore pstore.Peerstore
|
|
||||||
Protector pnet.Protector
|
|
||||||
Reporter metrics.Reporter
|
|
||||||
DisableSecio bool
|
|
||||||
EnableNAT bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(cfg *Config) error
|
// Option is a libp2p config option that can be given to the libp2p constructor
|
||||||
|
// (`libp2p.New`).
|
||||||
|
type Option = config.Option
|
||||||
|
|
||||||
func Transports(tpts ...transport.Transport) Option {
|
// ChainOptions chains multiple options into a single option.
|
||||||
|
func ChainOptions(opts ...Option) Option {
|
||||||
return func(cfg *Config) error {
|
return func(cfg *Config) error {
|
||||||
cfg.Transports = append(cfg.Transports, tpts...)
|
for _, opt := range opts {
|
||||||
return nil
|
if err := opt(cfg); err != nil {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ListenAddrStrings(s ...string) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
for _, addrstr := range s {
|
|
||||||
a, err := ma.NewMultiaddr(addrstr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfg.ListenAddrs = append(cfg.ListenAddrs, a)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenAddrs(addrs ...ma.Multiaddr) Option {
|
// New constructs a new libp2p node with the given options (falling back on
|
||||||
return func(cfg *Config) error {
|
// reasonable defaults).
|
||||||
cfg.ListenAddrs = append(cfg.ListenAddrs, addrs...)
|
//
|
||||||
return nil
|
// Canceling the passed context will stop the returned libp2p node.
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type transportEncOpt int
|
|
||||||
|
|
||||||
const (
|
|
||||||
EncPlaintext = transportEncOpt(0)
|
|
||||||
EncSecio = transportEncOpt(1)
|
|
||||||
)
|
|
||||||
|
|
||||||
func TransportEncryption(tenc ...transportEncOpt) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if len(tenc) != 1 {
|
|
||||||
return fmt.Errorf("can only specify a single transport encryption option right now")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: actually make this pluggable, otherwise tls will get tricky
|
|
||||||
switch tenc[0] {
|
|
||||||
case EncPlaintext:
|
|
||||||
cfg.DisableSecio = true
|
|
||||||
case EncSecio:
|
|
||||||
// noop
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unrecognized transport encryption option: %d", tenc[0])
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NoEncryption() Option {
|
|
||||||
return TransportEncryption(EncPlaintext)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NATPortMap() Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
cfg.EnableNAT = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Muxer(m mux.Transport) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.Muxer != nil {
|
|
||||||
return fmt.Errorf("cannot specify multiple muxer options")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.Muxer = m
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Peerstore(ps pstore.Peerstore) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.Peerstore != nil {
|
|
||||||
return fmt.Errorf("cannot specify multiple peerstore options")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.Peerstore = ps
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrivateNetwork(prot pnet.Protector) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.Protector != nil {
|
|
||||||
return fmt.Errorf("cannot specify multiple private network options")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.Protector = prot
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BandwidthReporter(rep metrics.Reporter) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.Reporter != nil {
|
|
||||||
return fmt.Errorf("cannot specify multiple bandwidth reporter options")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.Reporter = rep
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Identity(sk crypto.PrivKey) Option {
|
|
||||||
return func(cfg *Config) error {
|
|
||||||
if cfg.PeerKey != nil {
|
|
||||||
return fmt.Errorf("cannot specify multiple identities")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.PeerKey = sk
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(ctx context.Context, opts ...Option) (host.Host, error) {
|
func New(ctx context.Context, opts ...Option) (host.Host, error) {
|
||||||
|
return NewWithoutDefaults(ctx, append(opts, FallbackDefaults)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithoutDefaults constructs a new libp2p node with the given options but
|
||||||
|
// *without* falling back on reasonable defaults.
|
||||||
|
//
|
||||||
|
// Warning: This function should not be considered a stable interface. We may
|
||||||
|
// choose to add required services at any time and, by using this function, you
|
||||||
|
// opt-out of any defaults we may provide.
|
||||||
|
func NewWithoutDefaults(ctx context.Context, opts ...Option) (host.Host, error) {
|
||||||
var cfg Config
|
var cfg Config
|
||||||
for _, opt := range opts {
|
if err := cfg.Apply(opts...); err != nil {
|
||||||
if err := opt(&cfg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newWithCfg(ctx, &cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newWithCfg(ctx context.Context, cfg *Config) (host.Host, error) {
|
|
||||||
// If no key was given, generate a random 2048 bit RSA key
|
|
||||||
if cfg.PeerKey == nil {
|
|
||||||
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cfg.PeerKey = priv
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtain Peer ID from public key
|
|
||||||
pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return cfg.NewNode(ctx)
|
||||||
// Create a new blank peerstore if none was passed in
|
|
||||||
ps := cfg.Peerstore
|
|
||||||
if ps == nil {
|
|
||||||
ps = pstore.NewPeerstore()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set default muxer if none was passed in
|
|
||||||
muxer := cfg.Muxer
|
|
||||||
if muxer == nil {
|
|
||||||
muxer = DefaultMuxer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// If secio is disabled, don't add our private key to the peerstore
|
|
||||||
if !cfg.DisableSecio {
|
|
||||||
ps.AddPrivKey(pid, cfg.PeerKey)
|
|
||||||
ps.AddPubKey(pid, cfg.PeerKey.GetPublic())
|
|
||||||
}
|
|
||||||
|
|
||||||
swrm, err := swarm.NewSwarmWithProtector(ctx, cfg.ListenAddrs, pid, ps, cfg.Protector, muxer, cfg.Reporter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
netw := (*swarm.Network)(swrm)
|
|
||||||
|
|
||||||
hostOpts := &bhost.HostOpts{}
|
|
||||||
|
|
||||||
if cfg.EnableNAT {
|
|
||||||
hostOpts.NATManager = bhost.NewNATManager(netw)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bhost.NewHost(ctx, netw, hostOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DefaultMuxer() mux.Transport {
|
|
||||||
// Set up stream multiplexer
|
|
||||||
tpt := msmux.NewBlankTransport()
|
|
||||||
|
|
||||||
// By default, support yamux and multiplex
|
|
||||||
tpt.AddTransport("/yamux/1.0.0", yamux.DefaultTransport)
|
|
||||||
tpt.AddTransport("/mplex/6.3.0", mplex.DefaultTransport)
|
|
||||||
|
|
||||||
return tpt
|
|
||||||
}
|
|
||||||
|
|
||||||
func Defaults(cfg *Config) error {
|
|
||||||
// Create a multiaddress that listens on a random port on all interfaces
|
|
||||||
addr, err := ma.NewMultiaddr("/ip4/0.0.0.0/tcp/0")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.ListenAddrs = []ma.Multiaddr{addr}
|
|
||||||
cfg.Peerstore = pstore.NewPeerstore()
|
|
||||||
cfg.Muxer = DefaultMuxer()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package libp2p
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
crypto "github.com/libp2p/go-libp2p-crypto"
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
@@ -10,10 +11,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewHost(t *testing.T) {
|
func TestNewHost(t *testing.T) {
|
||||||
_, err := makeRandomHost(t, 9000)
|
h, err := makeRandomHost(t, 9000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
h.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBadTransportConstructor(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
h, err := New(ctx, Transport(func() {}))
|
||||||
|
if err == nil {
|
||||||
|
h.Close()
|
||||||
|
t.Fatal("expected an error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "libp2p_test.go") {
|
||||||
|
t.Error("expected error to contain debugging info")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInsecure(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
h, err := New(ctx, NoSecurity)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
h.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeRandomHost(t *testing.T, port int) (host.Host, error) {
|
func makeRandomHost(t *testing.T, port int) (host.Host, error) {
|
||||||
@@ -26,7 +49,9 @@ func makeRandomHost(t *testing.T, port int) (host.Host, error) {
|
|||||||
opts := []Option{
|
opts := []Option{
|
||||||
ListenAddrStrings(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port)),
|
ListenAddrStrings(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port)),
|
||||||
Identity(priv),
|
Identity(priv),
|
||||||
Muxer(DefaultMuxer()),
|
DefaultTransports,
|
||||||
|
DefaultMuxers,
|
||||||
|
DefaultSecurity,
|
||||||
NATPortMap(),
|
NATPortMap(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
243
options.go
Normal file
243
options.go
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
package libp2p
|
||||||
|
|
||||||
|
// This file contains all libp2p configuration options (except the defaults,
|
||||||
|
// those are in defaults.go)
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
config "github.com/libp2p/go-libp2p/config"
|
||||||
|
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
||||||
|
|
||||||
|
circuit "github.com/libp2p/go-libp2p-circuit"
|
||||||
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
|
ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr"
|
||||||
|
pnet "github.com/libp2p/go-libp2p-interface-pnet"
|
||||||
|
metrics "github.com/libp2p/go-libp2p-metrics"
|
||||||
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
|
filter "github.com/libp2p/go-maddr-filter"
|
||||||
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListenAddrStrings configures libp2p to listen on the given (unparsed)
|
||||||
|
// addresses.
|
||||||
|
func ListenAddrStrings(s ...string) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
for _, addrstr := range s {
|
||||||
|
a, err := ma.NewMultiaddr(addrstr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cfg.ListenAddrs = append(cfg.ListenAddrs, a)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenAddrs configures libp2p to listen on the given addresses.
|
||||||
|
func ListenAddrs(addrs ...ma.Multiaddr) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
cfg.ListenAddrs = append(cfg.ListenAddrs, addrs...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security configures libp2p to use the given security transport (or transport
|
||||||
|
// constructor).
|
||||||
|
//
|
||||||
|
// Name is the protocol name.
|
||||||
|
//
|
||||||
|
// The transport can be a constructed security.Transport or a function taking
|
||||||
|
// any subset of this libp2p node's:
|
||||||
|
// * Public key
|
||||||
|
// * Private key
|
||||||
|
// * Peer ID
|
||||||
|
// * Host
|
||||||
|
// * Network
|
||||||
|
// * Peerstore
|
||||||
|
func Security(name string, tpt interface{}) Option {
|
||||||
|
stpt, err := config.SecurityConstructor(tpt)
|
||||||
|
err = traceError(err, 1)
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if cfg.Insecure {
|
||||||
|
return fmt.Errorf("cannot use security transports with an insecure libp2p configuration")
|
||||||
|
}
|
||||||
|
cfg.SecurityTransports = append(cfg.SecurityTransports, config.MsSecC{SecC: stpt, ID: name})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoSecurity is an option that completely disables all transport security.
|
||||||
|
// It's incompatible with all other transport security protocols.
|
||||||
|
var NoSecurity Option = func(cfg *Config) error {
|
||||||
|
if len(cfg.SecurityTransports) > 0 {
|
||||||
|
return fmt.Errorf("cannot use security transports with an insecure libp2p configuration")
|
||||||
|
}
|
||||||
|
cfg.Insecure = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Muxer configures libp2p to use the given stream multiplexer (or stream
|
||||||
|
// multiplexer constructor).
|
||||||
|
//
|
||||||
|
// Name is the protocol name.
|
||||||
|
//
|
||||||
|
// The transport can be a constructed mux.Transport or a function taking any
|
||||||
|
// subset of this libp2p node's:
|
||||||
|
// * Peer ID
|
||||||
|
// * Host
|
||||||
|
// * Network
|
||||||
|
// * Peerstore
|
||||||
|
func Muxer(name string, tpt interface{}) Option {
|
||||||
|
mtpt, err := config.MuxerConstructor(tpt)
|
||||||
|
err = traceError(err, 1)
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cfg.Muxers = append(cfg.Muxers, config.MsMuxC{MuxC: mtpt, ID: name})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transport configures libp2p to use the given transport (or transport
|
||||||
|
// constructor).
|
||||||
|
//
|
||||||
|
// The transport can be a constructed transport.Transport or a function taking
|
||||||
|
// any subset of this libp2p node's:
|
||||||
|
// * Transport Upgrader (*tptu.Upgrader)
|
||||||
|
// * Host
|
||||||
|
// * Stream muxer (muxer.Transport)
|
||||||
|
// * Security transport (security.Transport)
|
||||||
|
// * Private network protector (pnet.Protector)
|
||||||
|
// * Peer ID
|
||||||
|
// * Private Key
|
||||||
|
// * Public Key
|
||||||
|
// * Address filter (filter.Filter)
|
||||||
|
// * Peerstore
|
||||||
|
func Transport(tpt interface{}) Option {
|
||||||
|
tptc, err := config.TransportConstructor(tpt)
|
||||||
|
err = traceError(err, 1)
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cfg.Transports = append(cfg.Transports, tptc)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peerstore configures libp2p to use the given peerstore.
|
||||||
|
func Peerstore(ps pstore.Peerstore) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.Peerstore != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple peerstore options")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Peerstore = ps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrivateNetwork configures libp2p to use the given private network protector.
|
||||||
|
func PrivateNetwork(prot pnet.Protector) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.Protector != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple private network options")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Protector = prot
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BandwidthReporter configures libp2p to use the given bandwidth reporter.
|
||||||
|
func BandwidthReporter(rep metrics.Reporter) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.Reporter != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple bandwidth reporter options")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Reporter = rep
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity configures libp2p to use the given private key to identify itself.
|
||||||
|
func Identity(sk crypto.PrivKey) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.PeerKey != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple identities")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.PeerKey = sk
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectionManager configures libp2p to use the given connection manager.
|
||||||
|
func ConnectionManager(connman ifconnmgr.ConnManager) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.ConnManager != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple connection managers")
|
||||||
|
}
|
||||||
|
cfg.ConnManager = connman
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddrsFactory configures libp2p to use the given address factory.
|
||||||
|
func AddrsFactory(factory config.AddrsFactory) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.AddrsFactory != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple address factories")
|
||||||
|
}
|
||||||
|
cfg.AddrsFactory = factory
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableRelay configures libp2p to enable the relay transport.
|
||||||
|
func EnableRelay(options ...circuit.RelayOpt) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
cfg.Relay = true
|
||||||
|
cfg.RelayOpts = options
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterAddresses configures libp2p to never dial nor accept connections from
|
||||||
|
// the given addresses.
|
||||||
|
func FilterAddresses(addrs ...*net.IPNet) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.Filters == nil {
|
||||||
|
cfg.Filters = filter.NewFilters()
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
cfg.Filters.AddDialFilter(addr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NATPortMap configures libp2p to use the default NATManager. The default
|
||||||
|
// NATManager will attempt to open a port in your network's firewall using UPnP.
|
||||||
|
func NATPortMap() Option {
|
||||||
|
return NATManager(bhost.NewNATManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NATManager will configure libp2p to use the requested NATManager. This
|
||||||
|
// function should be passed a NATManager *constructor* that takes a libp2p Network.
|
||||||
|
func NATManager(nm config.NATManagerC) Option {
|
||||||
|
return func(cfg *Config) error {
|
||||||
|
if cfg.NATManager != nil {
|
||||||
|
return fmt.Errorf("cannot specify multiple NATManagers")
|
||||||
|
}
|
||||||
|
cfg.NATManager = nm
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
@@ -8,7 +8,7 @@ import (
|
|||||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
||||||
|
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
netutil "github.com/libp2p/go-libp2p-netutil"
|
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||||
|
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
)
|
)
|
||||||
@@ -28,8 +28,8 @@ func TestMdnsDiscovery(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
a := bhost.New(netutil.GenSwarmNetwork(t, ctx))
|
a := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
b := bhost.New(netutil.GenSwarmNetwork(t, ctx))
|
b := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
sa, err := NewMdnsService(ctx, a, time.Second, "someTag")
|
sa, err := NewMdnsService(ctx, a, time.Second, "someTag")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -9,10 +9,8 @@ import (
|
|||||||
|
|
||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
goprocess "github.com/jbenet/goprocess"
|
goprocess "github.com/jbenet/goprocess"
|
||||||
circuit "github.com/libp2p/go-libp2p-circuit"
|
goprocessctx "github.com/jbenet/goprocess/context"
|
||||||
ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr"
|
ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr"
|
||||||
metrics "github.com/libp2p/go-libp2p-metrics"
|
|
||||||
mstream "github.com/libp2p/go-libp2p-metrics/stream"
|
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
@@ -67,8 +65,6 @@ type BasicHost struct {
|
|||||||
negtimeout time.Duration
|
negtimeout time.Duration
|
||||||
|
|
||||||
proc goprocess.Process
|
proc goprocess.Process
|
||||||
|
|
||||||
bwc metrics.Reporter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostOpts holds options that can be passed to NewHost in order to
|
// HostOpts holds options that can be passed to NewHost in order to
|
||||||
@@ -97,25 +93,14 @@ type HostOpts struct {
|
|||||||
|
|
||||||
// NATManager takes care of setting NAT port mappings, and discovering external addresses.
|
// NATManager takes care of setting NAT port mappings, and discovering external addresses.
|
||||||
// If omitted, this will simply be disabled.
|
// If omitted, this will simply be disabled.
|
||||||
NATManager NATManager
|
NATManager func(inet.Network) NATManager
|
||||||
|
|
||||||
// BandwidthReporter is used for collecting aggregate metrics of the
|
|
||||||
// bandwidth used by various protocols.
|
|
||||||
BandwidthReporter metrics.Reporter
|
|
||||||
|
|
||||||
// ConnManager is a libp2p connection manager
|
// ConnManager is a libp2p connection manager
|
||||||
ConnManager ifconnmgr.ConnManager
|
ConnManager ifconnmgr.ConnManager
|
||||||
|
|
||||||
// Relay indicates whether the host should use circuit relay transport
|
|
||||||
EnableRelay bool
|
|
||||||
|
|
||||||
// RelayOpts are options for the relay transport; only meaningful when Relay=true
|
|
||||||
RelayOpts []circuit.RelayOpt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHost constructs a new *BasicHost and activates it by attaching its stream and connection handlers to the given inet.Network.
|
// NewHost constructs a new *BasicHost and activates it by attaching its stream and connection handlers to the given inet.Network.
|
||||||
func NewHost(ctx context.Context, net inet.Network, opts *HostOpts) (*BasicHost, error) {
|
func NewHost(ctx context.Context, net inet.Network, opts *HostOpts) (*BasicHost, error) {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
|
||||||
h := &BasicHost{
|
h := &BasicHost{
|
||||||
network: net,
|
network: net,
|
||||||
mux: msmux.NewMultistreamMuxer(),
|
mux: msmux.NewMultistreamMuxer(),
|
||||||
@@ -124,11 +109,10 @@ func NewHost(ctx context.Context, net inet.Network, opts *HostOpts) (*BasicHost,
|
|||||||
maResolver: madns.DefaultResolver,
|
maResolver: madns.DefaultResolver,
|
||||||
}
|
}
|
||||||
|
|
||||||
h.proc = goprocess.WithTeardown(func() error {
|
h.proc = goprocessctx.WithContextAndTeardown(ctx, func() error {
|
||||||
if h.natmgr != nil {
|
if h.natmgr != nil {
|
||||||
h.natmgr.Close()
|
h.natmgr.Close()
|
||||||
}
|
}
|
||||||
cancel()
|
|
||||||
return h.Network().Close()
|
return h.Network().Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -152,18 +136,13 @@ func NewHost(ctx context.Context, net inet.Network, opts *HostOpts) (*BasicHost,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.NATManager != nil {
|
if opts.NATManager != nil {
|
||||||
h.natmgr = opts.NATManager
|
h.natmgr = opts.NATManager(net)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.MultiaddrResolver != nil {
|
if opts.MultiaddrResolver != nil {
|
||||||
h.maResolver = opts.MultiaddrResolver
|
h.maResolver = opts.MultiaddrResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.BandwidthReporter != nil {
|
|
||||||
h.bwc = opts.BandwidthReporter
|
|
||||||
h.ids.Reporter = opts.BandwidthReporter
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.ConnManager == nil {
|
if opts.ConnManager == nil {
|
||||||
h.cmgr = &ifconnmgr.NullConnMgr{}
|
h.cmgr = &ifconnmgr.NullConnMgr{}
|
||||||
} else {
|
} else {
|
||||||
@@ -173,20 +152,16 @@ func NewHost(ctx context.Context, net inet.Network, opts *HostOpts) (*BasicHost,
|
|||||||
|
|
||||||
net.SetConnHandler(h.newConnHandler)
|
net.SetConnHandler(h.newConnHandler)
|
||||||
net.SetStreamHandler(h.newStreamHandler)
|
net.SetStreamHandler(h.newStreamHandler)
|
||||||
|
|
||||||
if opts.EnableRelay {
|
|
||||||
err := circuit.AddRelayTransport(ctx, h, opts.RelayOpts...)
|
|
||||||
if err != nil {
|
|
||||||
h.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// New constructs and sets up a new *BasicHost with given Network and options.
|
// New constructs and sets up a new *BasicHost with given Network and options.
|
||||||
// Three options can be passed: NATPortMap, AddrsFactory, and metrics.Reporter.
|
// The following options can be passed:
|
||||||
|
// * NATPortMap
|
||||||
|
// * AddrsFactory
|
||||||
|
// * ifconnmgr.ConnManager
|
||||||
|
// * madns.Resolver
|
||||||
|
//
|
||||||
// This function is deprecated in favor of NewHost and HostOpts.
|
// This function is deprecated in favor of NewHost and HostOpts.
|
||||||
func New(net inet.Network, opts ...interface{}) *BasicHost {
|
func New(net inet.Network, opts ...interface{}) *BasicHost {
|
||||||
hostopts := &HostOpts{}
|
hostopts := &HostOpts{}
|
||||||
@@ -196,10 +171,8 @@ func New(net inet.Network, opts ...interface{}) *BasicHost {
|
|||||||
case Option:
|
case Option:
|
||||||
switch o {
|
switch o {
|
||||||
case NATPortMap:
|
case NATPortMap:
|
||||||
hostopts.NATManager = newNatManager(net)
|
hostopts.NATManager = NewNATManager
|
||||||
}
|
}
|
||||||
case metrics.Reporter:
|
|
||||||
hostopts.BandwidthReporter = o
|
|
||||||
case AddrsFactory:
|
case AddrsFactory:
|
||||||
hostopts.AddrsFactory = AddrsFactory(o)
|
hostopts.AddrsFactory = AddrsFactory(o)
|
||||||
case ifconnmgr.ConnManager:
|
case ifconnmgr.ConnManager:
|
||||||
@@ -270,10 +243,6 @@ func (h *BasicHost) newStreamHandler(s inet.Stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.SetProtocol(protocol.ID(protoID))
|
s.SetProtocol(protocol.ID(protoID))
|
||||||
|
|
||||||
if h.bwc != nil {
|
|
||||||
s = mstream.WrapStream(s, h.bwc)
|
|
||||||
}
|
|
||||||
log.Debugf("protocol negotiation took %s", took)
|
log.Debugf("protocol negotiation took %s", took)
|
||||||
|
|
||||||
go handle(protoID, s)
|
go handle(protoID, s)
|
||||||
@@ -366,10 +335,6 @@ func (h *BasicHost) NewStream(ctx context.Context, p peer.ID, pids ...protocol.I
|
|||||||
s.SetProtocol(selpid)
|
s.SetProtocol(selpid)
|
||||||
h.Peerstore().AddProtocols(p, selected)
|
h.Peerstore().AddProtocols(p, selected)
|
||||||
|
|
||||||
if h.bwc != nil {
|
|
||||||
s = mstream.WrapStream(s, h.bwc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,10 +368,6 @@ func (h *BasicHost) newStream(ctx context.Context, p peer.ID, pid protocol.ID) (
|
|||||||
|
|
||||||
s.SetProtocol(pid)
|
s.SetProtocol(pid)
|
||||||
|
|
||||||
if h.bwc != nil {
|
|
||||||
s = mstream.WrapStream(s, h.bwc)
|
|
||||||
}
|
|
||||||
|
|
||||||
lzcon := msmux.NewMSSelect(s, string(pid))
|
lzcon := msmux.NewMSSelect(s, string(pid))
|
||||||
return &streamWrapper{
|
return &streamWrapper{
|
||||||
Stream: s,
|
Stream: s,
|
||||||
@@ -536,11 +497,6 @@ func (h *BasicHost) Close() error {
|
|||||||
return h.proc.Close()
|
return h.proc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBandwidthReporter exposes the Host's bandiwth metrics reporter
|
|
||||||
func (h *BasicHost) GetBandwidthReporter() metrics.Reporter {
|
|
||||||
return h.bwc
|
|
||||||
}
|
|
||||||
|
|
||||||
type streamWrapper struct {
|
type streamWrapper struct {
|
||||||
inet.Stream
|
inet.Stream
|
||||||
rw io.ReadWriter
|
rw io.ReadWriter
|
||||||
|
@@ -8,11 +8,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
testutil "github.com/libp2p/go-testutil"
|
||||||
|
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
testutil "github.com/libp2p/go-libp2p-netutil"
|
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
protocol "github.com/libp2p/go-libp2p-protocol"
|
protocol "github.com/libp2p/go-libp2p-protocol"
|
||||||
|
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
madns "github.com/multiformats/go-multiaddr-dns"
|
madns "github.com/multiformats/go-multiaddr-dns"
|
||||||
)
|
)
|
||||||
@@ -20,8 +22,8 @@ import (
|
|||||||
func TestHostSimple(t *testing.T) {
|
func TestHostSimple(t *testing.T) {
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
h1 := New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := New(swarmt.GenSwarm(t, ctx))
|
||||||
defer h1.Close()
|
defer h1.Close()
|
||||||
defer h2.Close()
|
defer h2.Close()
|
||||||
|
|
||||||
@@ -74,7 +76,7 @@ func TestHostAddrsFactory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
h := New(testutil.GenSwarmNetwork(t, ctx), AddrsFactory(addrsFactory))
|
h := New(swarmt.GenSwarm(t, ctx), AddrsFactory(addrsFactory))
|
||||||
defer h.Close()
|
defer h.Close()
|
||||||
|
|
||||||
addrs := h.Addrs()
|
addrs := h.Addrs()
|
||||||
@@ -87,8 +89,8 @@ func TestHostAddrsFactory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getHostPair(ctx context.Context, t *testing.T) (host.Host, host.Host) {
|
func getHostPair(ctx context.Context, t *testing.T) (host.Host, host.Host) {
|
||||||
h1 := New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := New(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
h2pi := h2.Peerstore().PeerInfo(h2.ID())
|
h2pi := h2.Peerstore().PeerInfo(h2.ID())
|
||||||
if err := h1.Connect(ctx, h2pi); err != nil {
|
if err := h1.Connect(ctx, h2pi); err != nil {
|
||||||
@@ -193,8 +195,8 @@ func TestHostProtoPreknowledge(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
h1 := New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := New(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
conn := make(chan protocol.ID)
|
conn := make(chan protocol.ID)
|
||||||
handler := func(s inet.Stream) {
|
handler := func(s inet.Stream) {
|
||||||
@@ -358,7 +360,7 @@ func TestAddrResolution(t *testing.T) {
|
|||||||
}
|
}
|
||||||
resolver := &madns.Resolver{Backend: backend}
|
resolver := &madns.Resolver{Backend: backend}
|
||||||
|
|
||||||
h := New(testutil.GenSwarmNetwork(t, ctx), resolver)
|
h := New(swarmt.GenSwarm(t, ctx), resolver)
|
||||||
defer h.Close()
|
defer h.Close()
|
||||||
|
|
||||||
pi, err := pstore.InfoFromP2pAddr(p2paddr1)
|
pi, err := pstore.InfoFromP2pAddr(p2paddr1)
|
||||||
|
@@ -118,12 +118,12 @@ func (c *conn) NewStream() (inet.Stream, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) GetStreams() ([]inet.Stream, error) {
|
func (c *conn) GetStreams() []inet.Stream {
|
||||||
var out []inet.Stream
|
var out []inet.Stream
|
||||||
for e := c.streams.Front(); e != nil; e = e.Next() {
|
for e := c.streams.Front(); e != nil; e = e.Next() {
|
||||||
out = append(out, e.Value.(*stream))
|
out = append(out, e.Value.(*stream))
|
||||||
}
|
}
|
||||||
return out, nil
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalMultiaddr is the Multiaddr on this side
|
// LocalMultiaddr is the Multiaddr on this side
|
||||||
|
@@ -13,8 +13,6 @@ import (
|
|||||||
ic "github.com/libp2p/go-libp2p-crypto"
|
ic "github.com/libp2p/go-libp2p-crypto"
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
lgbl "github.com/libp2p/go-libp2p-loggables"
|
lgbl "github.com/libp2p/go-libp2p-loggables"
|
||||||
metrics "github.com/libp2p/go-libp2p-metrics"
|
|
||||||
mstream "github.com/libp2p/go-libp2p-metrics/stream"
|
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
@@ -44,7 +42,6 @@ var ClientVersion = "go-libp2p/3.3.4"
|
|||||||
type IDService struct {
|
type IDService struct {
|
||||||
Host host.Host
|
Host host.Host
|
||||||
|
|
||||||
Reporter metrics.Reporter
|
|
||||||
// connections undergoing identification
|
// connections undergoing identification
|
||||||
// for wait purposes
|
// for wait purposes
|
||||||
currid map[inet.Conn]chan struct{}
|
currid map[inet.Conn]chan struct{}
|
||||||
@@ -64,7 +61,7 @@ func NewIDService(h host.Host) *IDService {
|
|||||||
Host: h,
|
Host: h,
|
||||||
currid: make(map[inet.Conn]chan struct{}),
|
currid: make(map[inet.Conn]chan struct{}),
|
||||||
}
|
}
|
||||||
h.SetStreamHandler(ID, s.RequestHandler)
|
h.SetStreamHandler(ID, s.requestHandler)
|
||||||
h.Network().Notify((*netNotifiee)(s))
|
h.Network().Notify((*netNotifiee)(s))
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -95,21 +92,17 @@ func (ids *IDService) IdentifyConn(c inet.Conn) {
|
|||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer inet.FullClose(s)
|
||||||
|
|
||||||
s.SetProtocol(ID)
|
s.SetProtocol(ID)
|
||||||
|
|
||||||
if ids.Reporter != nil {
|
|
||||||
s = mstream.WrapStream(s, ids.Reporter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok give the response to our handler.
|
// ok give the response to our handler.
|
||||||
if err := msmux.SelectProtoOrFail(ID, s); err != nil {
|
if err := msmux.SelectProtoOrFail(ID, s); err != nil {
|
||||||
log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer(), logging.Metadata{"error": err})
|
log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer(), logging.Metadata{"error": err})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ids.ResponseHandler(s)
|
ids.responseHandler(s)
|
||||||
|
|
||||||
ids.currmu.Lock()
|
ids.currmu.Lock()
|
||||||
_, found := ids.currid[c]
|
_, found := ids.currid[c]
|
||||||
@@ -122,14 +115,10 @@ func (ids *IDService) IdentifyConn(c inet.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ids *IDService) RequestHandler(s inet.Stream) {
|
func (ids *IDService) requestHandler(s inet.Stream) {
|
||||||
defer s.Close()
|
defer inet.FullClose(s)
|
||||||
c := s.Conn()
|
c := s.Conn()
|
||||||
|
|
||||||
if ids.Reporter != nil {
|
|
||||||
s = mstream.WrapStream(s, ids.Reporter)
|
|
||||||
}
|
|
||||||
|
|
||||||
w := ggio.NewDelimitedWriter(s)
|
w := ggio.NewDelimitedWriter(s)
|
||||||
mes := pb.Identify{}
|
mes := pb.Identify{}
|
||||||
ids.populateMessage(&mes, s.Conn())
|
ids.populateMessage(&mes, s.Conn())
|
||||||
@@ -139,8 +128,7 @@ func (ids *IDService) RequestHandler(s inet.Stream) {
|
|||||||
c.RemotePeer(), c.RemoteMultiaddr())
|
c.RemotePeer(), c.RemoteMultiaddr())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ids *IDService) ResponseHandler(s inet.Stream) {
|
func (ids *IDService) responseHandler(s inet.Stream) {
|
||||||
defer s.Close()
|
|
||||||
c := s.Conn()
|
c := s.Conn()
|
||||||
|
|
||||||
r := ggio.NewDelimitedReader(s, 2048)
|
r := ggio.NewDelimitedReader(s, 2048)
|
||||||
|
@@ -6,9 +6,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
ic "github.com/libp2p/go-libp2p-crypto"
|
ic "github.com/libp2p/go-libp2p-crypto"
|
||||||
testutil "github.com/libp2p/go-libp2p-netutil"
|
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
|
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||||
identify "github.com/libp2p/go-libp2p/p2p/protocol/identify"
|
identify "github.com/libp2p/go-libp2p/p2p/protocol/identify"
|
||||||
|
|
||||||
blhost "github.com/libp2p/go-libp2p-blankhost"
|
blhost "github.com/libp2p/go-libp2p-blankhost"
|
||||||
@@ -20,8 +20,8 @@ func subtestIDService(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
h1 := blhost.NewBlankHost(testutil.GenSwarmNetwork(t, ctx))
|
h1 := blhost.NewBlankHost(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := blhost.NewBlankHost(testutil.GenSwarmNetwork(t, ctx))
|
h2 := blhost.NewBlankHost(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
h1p := h1.ID()
|
h1p := h1.ID()
|
||||||
h2p := h2.ID()
|
h2p := h2.ID()
|
||||||
@@ -65,7 +65,7 @@ func subtestIDService(t *testing.T) {
|
|||||||
ids2.IdentifyConn(c[0])
|
ids2.IdentifyConn(c[0])
|
||||||
|
|
||||||
addrs := h1.Peerstore().Addrs(h1p)
|
addrs := h1.Peerstore().Addrs(h1p)
|
||||||
addrs = append(addrs, c[0].RemoteMultiaddr(), forgetMe)
|
addrs = append(addrs, forgetMe)
|
||||||
|
|
||||||
// and the protocol versions.
|
// and the protocol versions.
|
||||||
t.Log("test peer2 has peer1 addrs correctly")
|
t.Log("test peer2 has peer1 addrs correctly")
|
||||||
|
@@ -5,17 +5,17 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
netutil "github.com/libp2p/go-libp2p-netutil"
|
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
pstore "github.com/libp2p/go-libp2p-peerstore"
|
pstore "github.com/libp2p/go-libp2p-peerstore"
|
||||||
|
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||||
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPing(t *testing.T) {
|
func TestPing(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
h1 := bhost.New(netutil.GenSwarmNetwork(t, ctx))
|
h1 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := bhost.New(netutil.GenSwarmNetwork(t, ctx))
|
h2 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
err := h1.Connect(ctx, pstore.PeerInfo{
|
err := h1.Connect(ctx, pstore.PeerInfo{
|
||||||
ID: h2.ID(),
|
ID: h2.ID(),
|
||||||
|
@@ -13,9 +13,9 @@ import (
|
|||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
testutil "github.com/libp2p/go-libp2p-netutil"
|
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
protocol "github.com/libp2p/go-libp2p-protocol"
|
protocol "github.com/libp2p/go-libp2p-protocol"
|
||||||
|
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.Logger("backpressure")
|
var log = logging.Logger("backpressure")
|
||||||
@@ -137,8 +137,8 @@ a problem.
|
|||||||
// ok that's enough setup. let's do it!
|
// ok that's enough setup. let's do it!
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
h1 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
// setup receiver handler
|
// setup receiver handler
|
||||||
h1.SetStreamHandler(protocol.TestingID, receiver)
|
h1.SetStreamHandler(protocol.TestingID, receiver)
|
||||||
@@ -274,8 +274,8 @@ func TestStBackpressureStreamWrite(t *testing.T) {
|
|||||||
|
|
||||||
// setup the networks
|
// setup the networks
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
h1 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
|
|
||||||
// setup sender handler on 1
|
// setup sender handler on 1
|
||||||
h1.SetStreamHandler(protocol.TestingID, sender)
|
h1.SetStreamHandler(protocol.TestingID, sender)
|
||||||
|
@@ -14,17 +14,10 @@ import (
|
|||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
host "github.com/libp2p/go-libp2p-host"
|
host "github.com/libp2p/go-libp2p-host"
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
testutil "github.com/libp2p/go-libp2p-netutil"
|
|
||||||
protocol "github.com/libp2p/go-libp2p-protocol"
|
protocol "github.com/libp2p/go-libp2p-protocol"
|
||||||
swarm "github.com/libp2p/go-libp2p-swarm"
|
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
|
||||||
ps "github.com/libp2p/go-peerstream"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
// change the garbage collect timeout for testing.
|
|
||||||
ps.GarbageCollectTimeout = 10 * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
var log = logging.Logger("reconnect")
|
var log = logging.Logger("reconnect")
|
||||||
|
|
||||||
func EchoStreamHandler(stream inet.Stream) {
|
func EchoStreamHandler(stream inet.Stream) {
|
||||||
@@ -109,8 +102,8 @@ func newSender() (chan sendChans, func(s inet.Stream)) {
|
|||||||
// TestReconnect tests whether hosts are able to disconnect and reconnect.
|
// TestReconnect tests whether hosts are able to disconnect and reconnect.
|
||||||
func TestReconnect2(t *testing.T) {
|
func TestReconnect2(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
h1 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
hosts := []host.Host{h1, h2}
|
hosts := []host.Host{h1, h2}
|
||||||
|
|
||||||
h1.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
|
h1.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
|
||||||
@@ -129,11 +122,11 @@ func TestReconnect2(t *testing.T) {
|
|||||||
// TestReconnect tests whether hosts are able to disconnect and reconnect.
|
// TestReconnect tests whether hosts are able to disconnect and reconnect.
|
||||||
func TestReconnect5(t *testing.T) {
|
func TestReconnect5(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
h1 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h1 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h2 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h2 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h3 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h3 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h4 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h4 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
h5 := bhost.New(testutil.GenSwarmNetwork(t, ctx))
|
h5 := bhost.New(swarmt.GenSwarm(t, ctx))
|
||||||
hosts := []host.Host{h1, h2, h3, h4, h5}
|
hosts := []host.Host{h1, h2, h3, h4, h5}
|
||||||
|
|
||||||
h1.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
|
h1.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
|
||||||
@@ -219,13 +212,11 @@ func SubtestConnSendDisc(t *testing.T, hosts []host.Host) {
|
|||||||
// close connection
|
// close connection
|
||||||
cs := h1.Network().Conns()
|
cs := h1.Network().Conns()
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
sc := c.(*swarm.Conn)
|
if c.LocalPeer() > c.RemotePeer() {
|
||||||
if sc.LocalPeer() > sc.RemotePeer() {
|
continue
|
||||||
continue // only close it on one side.
|
|
||||||
}
|
}
|
||||||
|
log.Debugf("closing: %s", c)
|
||||||
log.Debugf("closing: %s", sc.RawConn())
|
c.Close()
|
||||||
sc.Close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
171
package.json
171
package.json
@@ -18,21 +18,11 @@
|
|||||||
"name": "mdns",
|
"name": "mdns",
|
||||||
"version": "0.1.1"
|
"version": "0.1.1"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"hash": "QmWBug6eBS7AxRdCDVuSY5CnSit7cS2XnPFYJWqWDumhCG",
|
|
||||||
"name": "go-msgio",
|
|
||||||
"version": "0.0.3"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"hash": "QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx",
|
"hash": "QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx",
|
||||||
"name": "go-ipfs-util",
|
"name": "go-ipfs-util",
|
||||||
"version": "1.2.7"
|
"version": "1.2.7"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"hash": "QmUusaX99BZoELh7dmPgirqRQ1FAmMnmnBn3oiqDFGBUSc",
|
|
||||||
"name": "go-keyspace",
|
|
||||||
"version": "1.0.0"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"hash": "QmbXRda5H2K3MSQyWWxTMtd8DWuguEBUCe6hpxfXVpFUGj",
|
"hash": "QmbXRda5H2K3MSQyWWxTMtd8DWuguEBUCe6hpxfXVpFUGj",
|
||||||
"name": "go-multistream",
|
"name": "go-multistream",
|
||||||
@@ -54,24 +44,9 @@
|
|||||||
"version": "1.4.1"
|
"version": "1.4.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hash": "QmRK2LxanhK2gZq6k6R7vk5ZoYZk8ULSSTB7FzDsMUX6CB",
|
"hash": "QmcGXGdw9BWDysPJQHxJinjGHha3eEg4vzFETre4woNwcX",
|
||||||
"name": "go-multiaddr-net",
|
"name": "go-multiaddr-net",
|
||||||
"version": "1.5.7"
|
"version": "1.6.0"
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "QmZyZDi491cCNTLfAhwcaDii2Kg4pwKRkhqQzURGDvY6ua",
|
|
||||||
"name": "go-multihash",
|
|
||||||
"version": "1.0.7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "QmSMZwvs3n4GBikZ7hKzT17c3bk65FmyZo2JqtJ16swqCv",
|
|
||||||
"name": "multiaddr-filter",
|
|
||||||
"version": "1.0.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "QmaPHkZLbQQbvcyavn8q1GFHg6o6yeceyHFSJ3Pjf3p3TQ",
|
|
||||||
"name": "go-crypto",
|
|
||||||
"version": "0.0.0"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hash": "QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV",
|
"hash": "QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV",
|
||||||
@@ -83,38 +58,6 @@
|
|||||||
"name": "go-multiaddr",
|
"name": "go-multiaddr",
|
||||||
"version": "1.2.6"
|
"version": "1.2.6"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"hash": "QmYvsG72GsfLgUeSojXArjnU6L4Wmwk7wuAxtNLuyXcc1T",
|
|
||||||
"name": "randbo",
|
|
||||||
"version": "0.0.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "QmeQW4ayVqi7Jjay1SrP2wYydsH9KwSrzQBnqyC25gPFnG",
|
|
||||||
"name": "go-notifier",
|
|
||||||
"version": "1.0.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "QmWHgLqrghM9zw77nF6gdvT9ExQ2RB9pLxkd8sDHZf1rWb",
|
|
||||||
"name": "go-temp-err-catcher",
|
|
||||||
"version": "0.0.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hash": "QmVXXxPsnDY16szK4gPy1oz4qKd8HHshemX1miZR2frtJo",
|
|
||||||
"name": "go-peerstream",
|
|
||||||
"version": "2.1.5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "whyrusleeping",
|
|
||||||
"hash": "QmTy17Jm1foTnvUS9JXRhLbRQ3XuC64jPTjUfpB4mHz2QM",
|
|
||||||
"name": "mafmt",
|
|
||||||
"version": "1.2.5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "whyrusleeping",
|
|
||||||
"hash": "QmTd4Jgb4nbJq5uR55KJgGLyHWmM3dovS21D1HcwRneSLu",
|
|
||||||
"name": "gorocheck",
|
|
||||||
"version": "0.0.0"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmPDZJxtWGfcwLPazJxD4h3v3aDs43V7UNAVs3Jz1Wo7o4",
|
"hash": "QmPDZJxtWGfcwLPazJxD4h3v3aDs43V7UNAVs3Jz1Wo7o4",
|
||||||
@@ -123,33 +66,33 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmP47neqyP4NR9CKbjVogZ8U9Gybxfcfsa8HtPSPSxwiA8",
|
"hash": "QmQS7P1VV4JuqbXEEaPQZ5ERHDQuGp8qk26Gfdg9ZtP1Eb",
|
||||||
"name": "go-libp2p-secio",
|
"name": "go-libp2p-secio",
|
||||||
"version": "1.2.7"
|
"version": "2.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmdeiKhUy1TVGBaKxt7y1QmBDLBdisSrLJ1x58Eoj4PXUh",
|
"hash": "QmZb7hAgQEhW9dBbzBudU39gCeD4zbe6xafD52LUuF4cUN",
|
||||||
"name": "go-libp2p-peerstore",
|
"name": "go-libp2p-peerstore",
|
||||||
"version": "1.4.17"
|
"version": "1.4.18"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmPUHzTLPZFYqv8WqcBTuMFYTgeom4uHHEaxzk7bd5GYZB",
|
"hash": "QmYnjSGtvn7LhrxCvwrU9uDWxKyg28uBYeXvgzTDDDzVy4",
|
||||||
"name": "go-libp2p-transport",
|
"name": "go-libp2p-transport",
|
||||||
"version": "2.2.14"
|
"version": "3.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmdxKHpkZCTV3C7xdE1iJdPfFm5LVvMPvirdFmKu1TimzY",
|
"hash": "QmU7NiV3ZRJoNk8XZEKazs4AW7XQT1rQCrhh8cmhSjZgrC",
|
||||||
"name": "go-tcp-transport",
|
"name": "go-tcp-transport",
|
||||||
"version": "1.2.9"
|
"version": "2.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "Qmf2UAmRwDG4TvnkQpHZWPAzw7rpCYVhxmRXmYxXr5LD1g",
|
"hash": "QmYF6XMumtqvXtZfQKrCokXEdFvfy2i7tbpvSRzRrHyY8c",
|
||||||
"name": "go-maddr-filter",
|
"name": "go-maddr-filter",
|
||||||
"version": "1.1.6"
|
"version": "1.1.7"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
@@ -157,12 +100,6 @@
|
|||||||
"name": "go-libp2p-protocol",
|
"name": "go-libp2p-protocol",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "whyrusleeping",
|
|
||||||
"hash": "QmTGSre9j1otFgsr1opCUQDXTPSM6BTZnMWwPeA5nYJM7w",
|
|
||||||
"name": "go-addr-util",
|
|
||||||
"version": "1.2.7"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmUJzxQQ2kzwQubsMqBTr1NGDpLfh7pGA2E1oaJULcKDPq",
|
"hash": "QmUJzxQQ2kzwQubsMqBTr1NGDpLfh7pGA2E1oaJULcKDPq",
|
||||||
@@ -171,57 +108,45 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmYSQpi68jBLVUx62u543RVvnjjaQQDDxyopWWG31kiUkG",
|
"hash": "QmYj8wdn5sZEHX2XMDWGBvcXJNdzVbaVpHmXvhHBVZepen",
|
||||||
"name": "go-libp2p-conn",
|
|
||||||
"version": "1.7.7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "whyrusleeping",
|
|
||||||
"hash": "QmXoz9o2PT3tEzf7hicegwex5UgVP54n3k82K7jrWFyN86",
|
|
||||||
"name": "go-libp2p-net",
|
"name": "go-libp2p-net",
|
||||||
"version": "2.0.7"
|
"version": "3.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmVvu4bS5QLfS19ePkp5Wgzn2ZUma5oXTT9BgDFyQLxUZF",
|
"hash": "QmNnaGds3p4hfTqSH4KURKh8pBRcisAWYbNDEGeMZ7c3Hv",
|
||||||
"name": "go-libp2p-metrics",
|
"name": "go-libp2p-metrics",
|
||||||
"version": "2.0.6"
|
"version": "2.1.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmYDNqBAMWVMHKndYR35Sd8PfEVWBiDmpHYkuRJTunJDeJ",
|
"hash": "QmdHyfNVTZ5VtUx4Xz23z8wtnioSrFQ28XSfpVkdhQBkGA",
|
||||||
"name": "go-libp2p-interface-conn",
|
|
||||||
"version": "0.4.13"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "whyrusleeping",
|
|
||||||
"hash": "QmaSfSMvc1VPZ8JbMponFs4WHvF9FgEruF56opm5E1RgQA",
|
|
||||||
"name": "go-libp2p-host",
|
"name": "go-libp2p-host",
|
||||||
"version": "2.1.8"
|
"version": "3.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmRpKdg1xs4Yyrn9yrVYRBp7AQqyRxMLpD6Jgp1eZAGqEr",
|
"hash": "QmPzT3rJnSP8VFP1kw7Ly7HP8AprKNZtwLHXHnxfVSbWT3",
|
||||||
"name": "go-libp2p-swarm",
|
"name": "go-libp2p-swarm",
|
||||||
"version": "2.1.9"
|
"version": "3.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmXtFH52dAPCq5i4iYjr1g8xVFVJD3fwKWWyNHjVB4sHRp",
|
"hash": "QmQF7htcTXeVqdTg4fKPGU59PeeTpsFgn9UquiixwbTPG1",
|
||||||
"name": "go-libp2p-nat",
|
"name": "go-libp2p-nat",
|
||||||
"version": "0.0.8"
|
"version": "0.8.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "Qma2UuHusnaFV24DgeZ5hyrM9uc4UdyVaZbtn2FQsPRhES",
|
"hash": "Qmb3r9qUR7PnkyUKztmXp8sQhzXZHGmRg7fR5zsB1ebWMj",
|
||||||
"name": "go-libp2p-netutil",
|
"name": "go-libp2p-netutil",
|
||||||
"version": "0.3.13"
|
"version": "0.4.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
"hash": "QmYEmPwCBe7ZUFfuymozopHTuF3JXejvJPDAjwtyQCrsDi",
|
"hash": "QmQ6ASb73YCy77TLfxzKnzQFUyFKMQzDhmjwjaQp6rxK34",
|
||||||
"name": "go-libp2p-blankhost",
|
"name": "go-libp2p-blankhost",
|
||||||
"version": "0.2.8"
|
"version": "0.3.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
@@ -255,9 +180,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "vyzo",
|
"author": "vyzo",
|
||||||
"hash": "QmR5sXZi68rm9m2E3KiXj6hE5m3GeLaDjbLPUeV6W3MLR8",
|
"hash": "QmNXLcLAcfo8yp59FxFQJNa7pDbUUw97QN9GwefWWFK4hk",
|
||||||
"name": "go-libp2p-circuit",
|
"name": "go-libp2p-circuit",
|
||||||
"version": "2.0.14"
|
"version": "2.1.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "lgierth",
|
"author": "lgierth",
|
||||||
@@ -267,9 +192,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "why",
|
"author": "why",
|
||||||
"hash": "QmfQNieWBPwmnUjXWPZbjJPzhNwFFabTb5RQ79dyVWGujQ",
|
"hash": "QmWCWsDQnnQ9Mo9V3GK8TSR91662FdFxjjqPX8YbHC8Ltz",
|
||||||
"name": "go-libp2p-interface-connmgr",
|
"name": "go-libp2p-interface-connmgr",
|
||||||
"version": "0.0.8"
|
"version": "0.0.7"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "whyrusleeping",
|
"author": "whyrusleeping",
|
||||||
@@ -288,6 +213,42 @@
|
|||||||
"hash": "QmcBWojPoNh4qm7zvv4qiepvCnnc7ALS9qcp7TNwwxT1gT",
|
"hash": "QmcBWojPoNh4qm7zvv4qiepvCnnc7ALS9qcp7TNwwxT1gT",
|
||||||
"name": "go.uuid",
|
"name": "go.uuid",
|
||||||
"version": "1.1.0"
|
"version": "1.1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "whyrusleeping",
|
||||||
|
"hash": "QmTeRSFgnXRCh13sxsZkLTVCc1diUbZiT5mkGUgkR1J1on",
|
||||||
|
"name": "go-ws-transport",
|
||||||
|
"version": "2.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "stebalien",
|
||||||
|
"hash": "QmRYk8zWrXSkXsE16vM8yxByqM6eVvnXzDXKGvHFJJubVc",
|
||||||
|
"name": "go-conn-security-multistream",
|
||||||
|
"version": "0.1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Stebalien",
|
||||||
|
"hash": "QmSieFUauuYnroStqmRAEgu9BMXDNY5LbtNgzXcFitBKXQ",
|
||||||
|
"name": "go-conn-security",
|
||||||
|
"version": "0.1.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "libp2p",
|
||||||
|
"hash": "QmW7Ump7YyBMr712Ta3iEVh3ZYcfVvJaPryfbCnyE826b4",
|
||||||
|
"name": "go-libp2p-interface-pnet",
|
||||||
|
"version": "3.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "whyrusleeping",
|
||||||
|
"hash": "QmY9JXR3FupnYAYJWK9aMr9bCpqWKcToQ1tz8DVGTrHpHw",
|
||||||
|
"name": "go-stream-muxer",
|
||||||
|
"version": "3.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "steb",
|
||||||
|
"hash": "Qmf3ejfGWR8Bd3wKFBvwYGFMJ9TeKJwYJUc2WchXjMxzg7",
|
||||||
|
"name": "go-libp2p-transport-upgrader",
|
||||||
|
"version": "0.1.0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"gxVersion": "0.4.0",
|
"gxVersion": "0.4.0",
|
||||||
|
Reference in New Issue
Block a user