Files
2024-12-04 14:21:50 -04:00

169 lines
3.9 KiB
Go

package main
import (
"context"
"fmt"
"net"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
"github.com/libp2p/go-libp2p/p2p/protocol/ping"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
golog "github.com/ipfs/go-log/v2"
)
func assert(err error) {
if err != nil {
panic("ERROR!!!: " + err.Error())
}
}
const P_CUSTOM = 887
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
multiaddr.AddProtocol(multiaddr.Protocol{
Name: "custom",
Code: P_CUSTOM,
VCode: multiaddr.CodeToVarint(P_CUSTOM),
Size: multiaddr.LengthPrefixedVarSize,
Transcoder: multiaddr.TranscoderP2P,
})
golog.SetAllLoggers(golog.LevelInfo)
var customHosts []host.Host
var customProtocols []*CustomProtocol
for i := 0; i < 10; i++ {
h, err := makeCustomHost()
assert(err)
customHosts = append(customHosts, h)
}
for i := 0; i < 10; i++ {
p, err := makeCustomProto(ctx, customHosts[i], customHosts)
assert(err)
customProtocols = append(customProtocols, p)
}
// nodeA and B are not connected directly. Message will go thru via custom protocol
nodeA, err := makeBasicHost(customProtocols[0])
assert(err)
nodeB, err := makeBasicHost(customProtocols[9])
assert(err)
fmt.Println("NODEA", nodeA.Addrs(), nodeA.ID())
fmt.Println("Custom0", customHosts[0].Addrs(), customHosts[0].ID())
fmt.Println("NODEB", nodeB.Addrs(), nodeB.ID())
fmt.Println("Custom9", customHosts[9].Addrs(), customHosts[9].ID())
nodeA.Peerstore().AddAddrs(nodeB.ID(), nodeB.Addrs(), peerstore.PermanentAddrTTL)
pingService := ping.NewPingService(nodeA)
fmt.Println("==================================================================")
result := pingService.Ping(ctx, nodeB.ID())
fmt.Println("Waiting for ping result...")
fmt.Println(<-result)
<-ctx.Done()
}
func makeCustomHost() (host.Host, error) {
hostAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", "0.0.0.0", 0))
if err != nil {
return nil, err
}
tcpAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/tcp/%d", hostAddr.Port))
if err != nil {
return nil, err
}
hostAddrMA, err := manet.FromNetAddr(hostAddr)
if err != nil {
return nil, err
}
tcpAddrMa := hostAddrMA.Encapsulate(tcpAddr)
h, err := libp2p.New(
libp2p.ListenAddrs(tcpAddrMa),
libp2p.Transport(tcp.NewTCPTransport),
)
if err != nil {
return nil, err
}
return h, nil
}
func makeCustomProto(ctx context.Context, h host.Host, listOfNodes []host.Host) (*CustomProtocol, error) {
var maddrs []multiaddr.Multiaddr
for _, m := range listOfNodes {
maddrs = append(maddrs, EncapsulatePeerID(m.ID(), m.Addrs()[0]))
}
customProto, err := NewCustomProtocol(h, maddrs)
if err != nil {
return nil, err
}
customProto.Start(ctx)
return customProto, nil
}
func makeBasicHost(myCustomProtocol *CustomProtocol) (host.Host, error) {
// custom multiaddress
hostAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", "0.0.0.0", 0))
if err != nil {
return nil, err
}
hostAddrMA, err := manet.FromNetAddr(hostAddr)
if err != nil {
return nil, err
}
customAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/custom/%s", myCustomProtocol.host.ID()))
if err != nil {
return nil, err
}
customMA := hostAddrMA.Encapsulate(customAddr)
// tcp multiaddress
// hostAddr2, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", "0.0.0.0", 0))
// if err != nil {
// return nil, err
// }
// hostAddrMA2, err := manet.FromNetAddr(hostAddr2)
// if err != nil {
// return nil, err
// }
h, err := libp2p.New(
libp2p.ListenAddrs(customMA), //, hostAddrMA2),
libp2p.Transport(NewCustomTransport, WithCustomNode(myCustomProtocol)),
libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport),
)
if err != nil {
return nil, err
}
myCustomProtocol.setParentID(h.ID())
return h, nil
}