// 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 }