lbcd/peer/example_test.go
Wilmer Paulino fdb479f121
peer: allow external testing of peer.Peer
The previous use of allowSelfConns prevented this, as users aren't able
to invoke peer.TstAllowSelfConns themselves due to being part of a test
file, which aren't exported at the library level, leading to a
"disconnecting peer connected to self" error upon establishing a mock
connection between two peers. By including the option at the config
level instead (false by default, prevents connections to self) we enable
users of the peer library to properly test the behavior of the peer.Peer
struct externally.
2021-03-11 18:24:13 -08:00

115 lines
3.3 KiB
Go

// Copyright (c) 2015-2018 The btcsuite developers
// Copyright (c) 2016-2018 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package peer_test
import (
"fmt"
"net"
"time"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/peer"
"github.com/btcsuite/btcd/wire"
)
// mockRemotePeer creates a basic inbound peer listening on the simnet port for
// use with Example_peerConnection. It does not return until the listner is
// active.
func mockRemotePeer() error {
// Configure peer to act as a simnet node that offers no services.
peerCfg := &peer.Config{
UserAgentName: "peer", // User agent name to advertise.
UserAgentVersion: "1.0.0", // User agent version to advertise.
ChainParams: &chaincfg.SimNetParams,
TrickleInterval: time.Second * 10,
AllowSelfConns: true,
}
// Accept connections on the simnet port.
listener, err := net.Listen("tcp", "127.0.0.1:18555")
if err != nil {
return err
}
go func() {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("Accept: error %v\n", err)
return
}
// Create and start the inbound peer.
p := peer.NewInboundPeer(peerCfg)
p.AssociateConnection(conn)
}()
return nil
}
// This example demonstrates the basic process for initializing and creating an
// outbound peer. Peers negotiate by exchanging version and verack messages.
// For demonstration, a simple handler for version message is attached to the
// peer.
func Example_newOutboundPeer() {
// Ordinarily this will not be needed since the outbound peer will be
// connecting to a remote peer, however, since this example is executed
// and tested, a mock remote peer is needed to listen for the outbound
// peer.
if err := mockRemotePeer(); err != nil {
fmt.Printf("mockRemotePeer: unexpected error %v\n", err)
return
}
// Create an outbound peer that is configured to act as a simnet node
// that offers no services and has listeners for the version and verack
// messages. The verack listener is used here to signal the code below
// when the handshake has been finished by signalling a channel.
verack := make(chan struct{})
peerCfg := &peer.Config{
UserAgentName: "peer", // User agent name to advertise.
UserAgentVersion: "1.0.0", // User agent version to advertise.
ChainParams: &chaincfg.SimNetParams,
Services: 0,
TrickleInterval: time.Second * 10,
Listeners: peer.MessageListeners{
OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject {
fmt.Println("outbound: received version")
return nil
},
OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) {
verack <- struct{}{}
},
},
AllowSelfConns: true,
}
p, err := peer.NewOutboundPeer(peerCfg, "127.0.0.1:18555")
if err != nil {
fmt.Printf("NewOutboundPeer: error %v\n", err)
return
}
// Establish the connection to the peer address and mark it connected.
conn, err := net.Dial("tcp", p.Addr())
if err != nil {
fmt.Printf("net.Dial: error %v\n", err)
return
}
p.AssociateConnection(conn)
// Wait for the verack message or timeout in case of failure.
select {
case <-verack:
case <-time.After(time.Second * 1):
fmt.Printf("Example_peerConnection: verack timeout")
}
// Disconnect the peer.
p.Disconnect()
p.WaitForDisconnect()
// Output:
// outbound: received version
}