Skip to content

Commit

Permalink
Merge pull request #11 from 0xbillw/billw/nodeinfo2_example
Browse files Browse the repository at this point in the history
another example of nodeinfo running separately from the server and client
  • Loading branch information
drgomesp committed Aug 14, 2023
2 parents f3864df + 3fd9cb8 commit 8585bc1
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ _testmain.go
dist/

dist/

*.out
157 changes: 157 additions & 0 deletions examples/nodeinfo2/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package main

import (
"context"
"crypto/rand"
"flag"
"fmt"
"io"
mrand "math/rand"
"sort"
"time"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/multiformats/go-multiaddr"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

libp2pgrpc "github.com/drgomesp/go-libp2p-grpc"
proto "github.com/drgomesp/go-libp2p-grpc/proto/v1"
golog "github.com/ipfs/go-log/v2"
)

var log = golog.Logger("demo_main")

type NodeService struct {
proto.UnimplementedNodeServiceServer

host host.Host
}

// Info returns information about the node service's underlying host.
func (s *NodeService) Info(_ context.Context, _ *proto.NodeInfoRequest) (*proto.NodeInfoResponse, error) {
peers := make([]string, 0)
for _, peer := range s.host.Peerstore().Peers() {
peers = append(peers, peer.ShortString())
}
sort.Strings(peers)
log.Debugw("handle node info request")

return &proto.NodeInfoResponse{
Id: s.host.ID().String(),
Addresses: func() []string {
res := make([]string, 0)

for _, addr := range s.host.Addrs() {
res = append(res, addr.String())
}

return res
}(),
Protocols: protocol.ConvertToStrings(s.host.Mux().Protocols()),
Peers: peers,
}, nil
}

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// LibP2P code uses golog to log messages. They log with different
// string IDs (i.e. "swarm"). We can control the verbosity level for
// all loggers with:
golog.SetAllLoggers(golog.LevelDebug)

// Parse options from the command line
listenF := flag.Int("l", 10000, "wait for incoming connections")
targetF := flag.String("d", "", "target peer to dial")
seedF := flag.Int64("seed", 0, "set random seed for id generation")
flag.Parse()

var r io.Reader
if *seedF == 0 {
r = rand.Reader
} else {
r = mrand.New(mrand.NewSource(*seedF))
}
// Generate a key pair for this host. We will use it at least
// to obtain a valid host ID.
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, -1, r)
check(err)

if *targetF == "" {
// for server
m4, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", *listenF))
check(err)
ha, err := libp2p.New(libp2p.Identity(priv), libp2p.ListenAddrs(m4), libp2p.DefaultSecurity)
check(err)
defer ha.Close()

fullAddr := getHostAddress(ha)
log.Debugf("I am %s", fullAddr)
srv, err := libp2pgrpc.NewGrpcServer(ctx, ha)
check(err)
proto.RegisterNodeServiceServer(srv, &NodeService{host: ha})
log.Infow("gRPC server is ready")
go srv.Serve()
// Run until canceled.
<-ctx.Done()

} else {
// for client
ha, err := libp2p.New(libp2p.Identity(priv), libp2p.DefaultSecurity)
check(err)
defer ha.Close()

// Turn the targetPeer into a multiaddr.
maddr, err := multiaddr.NewMultiaddr(*targetF)
check(err)
// Extract the peer ID from the multiaddr.
info, err := peer.AddrInfoFromP2pAddr(maddr)
check(err)

log.Debugw("Will get remote node info", "target", *targetF)
// We have a peer ID and a targetAddr, so we add it to the peerstore
// so LibP2P knows how to contact it
ha.Peerstore().AddAddrs(info.ID, info.Addrs, peerstore.PermanentAddrTTL)

// ha will act as the grpc client here, dialing the h2 server
client := libp2pgrpc.NewClient(ha, libp2pgrpc.ProtocolID)
opts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials())}
conn, err := client.Dial(ctx, info.ID, opts...)
check(err)

nsc := proto.NewNodeServiceClient(conn)
for i := 0; i < 3; i++ {
req := proto.NodeInfoRequest{}
res, err := nsc.Info(ctx, &req)
if err != nil {
log.Fatalf("error while calling NodeService RPC: %v", err)
}
log.Debugw("Response from remote", "i", i, "nodeInfo", res)
time.Sleep(2 * time.Second)
}
}
log.Debugw("exit")
}

func check(err error) {
if err != nil {
log.Fatal(err)
}
}

func getHostAddress(ha host.Host) string {
// Build host multiaddress
hostAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", ha.ID().Pretty()))

// Now we can build a full multiaddress to reach this host
// by encapsulating both addresses:
addr := ha.Addrs()[0]
return addr.Encapsulate(hostAddr).String()
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
github.com/ipfs/go-log/v2 v2.5.1
github.com/libp2p/go-libp2p v0.29.1
github.com/libp2p/go-libp2p-gostream v0.6.0
github.com/multiformats/go-multiaddr v0.10.1
Expand Down Expand Up @@ -36,7 +37,6 @@ require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
Expand Down

0 comments on commit 8585bc1

Please sign in to comment.