Files
dejo-node/internal/p2p/p2p.go
2025-05-23 10:44:32 -03:00

81 lines
1.9 KiB
Go

package p2p
import (
"context"
"crypto/rand"
"fmt"
host "github.com/libp2p/go-libp2p/core/host"
libp2p "github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
)
const ProtocolID = "/dejo/1.0.0"
// P2PNode representa um nó da rede P2P da DEJO.
type P2PNode struct {
Host host.Host
PeerChan chan peer.AddrInfo
}
// NewP2PNode cria um novo nó libp2p.
func NewP2PNode(ctx context.Context) (*P2PNode, error) {
priv, _, _ := crypto.GenerateKeyPairWithReader(crypto.Ed25519, -1, rand.Reader)
h, err := libp2p.New(
libp2p.Identity(priv),
libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"),
)
if err != nil {
return nil, err
}
node := &P2PNode{
Host: h,
PeerChan: make(chan peer.AddrInfo),
}
// Handler para conexões recebidas
h.SetStreamHandler(ProtocolID, func(s network.Stream) {
buf := make([]byte, 1024)
s.Read(buf)
fmt.Printf("📡 Recebido: %s\n", string(buf))
s.Close()
})
return node, nil
}
// HandlePeerFound é chamado quando um novo peer é descoberto.
func (p *P2PNode) HandlePeerFound(pi peer.AddrInfo) {
fmt.Println("👋 Novo peer descoberto:", pi.ID)
p.PeerChan <- pi
}
// ConnectToPeers tenta se conectar aos peers encontrados.
func (p *P2PNode) ConnectToPeers(ctx context.Context) {
go func() {
for pi := range p.PeerChan {
if err := p.Host.Connect(ctx, pi); err != nil {
fmt.Println("Erro ao conectar ao peer:", err)
} else {
fmt.Println("🔗 Conectado ao peer:", pi.ID)
}
}
}()
}
// Broadcast envia uma mensagem para todos os peers conectados.
func (p *P2PNode) Broadcast(msg string) {
for _, c := range p.Host.Network().Peers() {
stream, err := p.Host.NewStream(context.Background(), c, ProtocolID)
if err != nil {
fmt.Println("Erro ao abrir stream:", err)
continue
}
stream.Write([]byte(msg))
stream.Close()
}
}