mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-03 10:33:45 +00:00
115 lines
2.7 KiB
Go
115 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/ethereum/go-ethereum/node"
|
|
"github.com/ethereum/go-ethereum/p2p"
|
|
"github.com/ethereum/go-ethereum/p2p/simulations"
|
|
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
|
"github.com/ethereum/go-ethereum/rpc"
|
|
)
|
|
|
|
// main() starts a simulation session which is capable of creating in-memory
|
|
// simulation networks containing nodes running a simple ping-pong protocol
|
|
func main() {
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
|
|
log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
|
|
|
services := map[string]adapters.ServiceFunc{
|
|
"ping-pong": func(id *adapters.NodeId) node.Service {
|
|
return newPingPongService(id)
|
|
},
|
|
}
|
|
|
|
c, quitc := simulations.NewSessionController(simulations.DefaultNet(services, "ping-pong"))
|
|
simulations.StartRestApiServer("8888", c)
|
|
// wait until server shuts down
|
|
<-quitc
|
|
|
|
}
|
|
|
|
// pingPongService runs a ping-pong protocol between nodes where each node
|
|
// sends a ping to all its connected peers every 10s and receives a pong in
|
|
// return
|
|
type pingPongService struct {
|
|
id *adapters.NodeId
|
|
log log.Logger
|
|
}
|
|
|
|
func newPingPongService(id *adapters.NodeId) *pingPongService {
|
|
return &pingPongService{
|
|
id: id,
|
|
log: log.New("node.id", id),
|
|
}
|
|
}
|
|
|
|
func (p *pingPongService) Protocols() []p2p.Protocol {
|
|
return []p2p.Protocol{{
|
|
Name: "ping-pong",
|
|
Version: 1,
|
|
Length: 2,
|
|
Run: p.Run,
|
|
}}
|
|
}
|
|
|
|
func (p *pingPongService) APIs() []rpc.API {
|
|
return nil
|
|
}
|
|
|
|
func (p *pingPongService) Start(server p2p.Server) error {
|
|
p.log.Info("ping-pong service starting")
|
|
return nil
|
|
}
|
|
|
|
func (p *pingPongService) Stop() error {
|
|
p.log.Info("ping-pong service stopping")
|
|
return nil
|
|
}
|
|
|
|
const (
|
|
pingMsgCode = iota
|
|
pongMsgCode
|
|
)
|
|
|
|
// Run implements the ping-pong protocol which sends ping messages to the peer
|
|
// at 10s intervals, and responds to pings with pong messages.
|
|
func (p *pingPongService) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
|
|
log := p.log.New("peer.id", peer.ID())
|
|
|
|
errC := make(chan error)
|
|
go func() {
|
|
for range time.Tick(10 * time.Second) {
|
|
log.Info("sending ping")
|
|
if err := p2p.Send(rw, pingMsgCode, "PING"); err != nil {
|
|
errC <- err
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
go func() {
|
|
for {
|
|
msg, err := rw.ReadMsg()
|
|
if err != nil {
|
|
errC <- err
|
|
return
|
|
}
|
|
payload, err := ioutil.ReadAll(msg.Payload)
|
|
if err != nil {
|
|
errC <- err
|
|
return
|
|
}
|
|
log.Info("received message", "msg.code", msg.Code, "msg.payload", string(payload))
|
|
if msg.Code == pingMsgCode {
|
|
log.Info("sending pong")
|
|
go p2p.Send(rw, pongMsgCode, "PONG")
|
|
}
|
|
}
|
|
}()
|
|
return <-errC
|
|
}
|