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() } }