github.com/decred/dcrlnd@v0.7.6/watchtower/wtmock/peer.go (about)

     1  package wtmock
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"time"
     7  
     8  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
     9  	"github.com/decred/dcrlnd/watchtower/wtserver"
    10  )
    11  
    12  // MockPeer emulates a single endpoint of brontide transport.
    13  type MockPeer struct {
    14  	remotePub  *secp256k1.PublicKey
    15  	remoteAddr net.Addr
    16  	localPub   *secp256k1.PublicKey
    17  	localAddr  net.Addr
    18  
    19  	IncomingMsgs chan []byte
    20  	OutgoingMsgs chan []byte
    21  
    22  	writeDeadline <-chan time.Time
    23  	readDeadline  <-chan time.Time
    24  
    25  	RemoteQuit chan struct{}
    26  	Quit       chan struct{}
    27  }
    28  
    29  // NewMockPeer returns a fresh MockPeer.
    30  func NewMockPeer(lpk, rpk *secp256k1.PublicKey, addr net.Addr,
    31  	bufferSize int) *MockPeer {
    32  
    33  	return &MockPeer{
    34  		remotePub:  rpk,
    35  		remoteAddr: addr,
    36  		localAddr: &net.TCPAddr{
    37  			IP:   net.IP{0x32, 0x31, 0x30, 0x29},
    38  			Port: 36723,
    39  		},
    40  		localPub:     lpk,
    41  		IncomingMsgs: make(chan []byte, bufferSize),
    42  		OutgoingMsgs: make(chan []byte, bufferSize),
    43  		Quit:         make(chan struct{}),
    44  	}
    45  }
    46  
    47  // NewMockConn establishes a bidirectional connection between two MockPeers.
    48  func NewMockConn(localPk, remotePk *secp256k1.PublicKey,
    49  	localAddr, remoteAddr net.Addr,
    50  	bufferSize int) (*MockPeer, *MockPeer) {
    51  
    52  	localPeer := &MockPeer{
    53  		remotePub:    remotePk,
    54  		remoteAddr:   remoteAddr,
    55  		localPub:     localPk,
    56  		localAddr:    localAddr,
    57  		IncomingMsgs: make(chan []byte, bufferSize),
    58  		OutgoingMsgs: make(chan []byte, bufferSize),
    59  		Quit:         make(chan struct{}),
    60  	}
    61  
    62  	remotePeer := &MockPeer{
    63  		remotePub:    localPk,
    64  		remoteAddr:   localAddr,
    65  		localPub:     remotePk,
    66  		localAddr:    remoteAddr,
    67  		IncomingMsgs: localPeer.OutgoingMsgs,
    68  		OutgoingMsgs: localPeer.IncomingMsgs,
    69  		Quit:         make(chan struct{}),
    70  	}
    71  
    72  	localPeer.RemoteQuit = remotePeer.Quit
    73  	remotePeer.RemoteQuit = localPeer.Quit
    74  
    75  	return localPeer, remotePeer
    76  }
    77  
    78  // Write sends the raw bytes as the next full message read to the remote peer.
    79  // The write will fail if either party closes the connection or the write
    80  // deadline expires. The passed bytes slice is copied before sending, thus the
    81  // bytes may be reused once the method returns.
    82  func (p *MockPeer) Write(b []byte) (n int, err error) {
    83  	bb := make([]byte, len(b))
    84  	copy(bb, b)
    85  
    86  	select {
    87  	case p.OutgoingMsgs <- bb:
    88  		return len(b), nil
    89  	case <-p.writeDeadline:
    90  		return 0, fmt.Errorf("write timeout expired")
    91  	case <-p.RemoteQuit:
    92  		return 0, fmt.Errorf("remote closed connected")
    93  	case <-p.Quit:
    94  		return 0, fmt.Errorf("connection closed")
    95  	}
    96  }
    97  
    98  // Close tearsdown the connection, and fails any pending reads or writes.
    99  func (p *MockPeer) Close() error {
   100  	select {
   101  	case <-p.Quit:
   102  		return fmt.Errorf("connection already closed")
   103  	default:
   104  		close(p.Quit)
   105  		return nil
   106  	}
   107  }
   108  
   109  // ReadNextMessage returns the raw bytes of the next full message read from the
   110  // remote peer. The read will fail if either party closes the connection or the
   111  // read deadline expires.
   112  func (p *MockPeer) ReadNextMessage() ([]byte, error) {
   113  	select {
   114  	case b := <-p.IncomingMsgs:
   115  		return b, nil
   116  	case <-p.readDeadline:
   117  		return nil, fmt.Errorf("read timeout expired")
   118  	case <-p.RemoteQuit:
   119  		return nil, fmt.Errorf("remote closed connected")
   120  	case <-p.Quit:
   121  		return nil, fmt.Errorf("connection closed")
   122  	}
   123  }
   124  
   125  // SetWriteDeadline initializes a timer that will cause any pending writes to
   126  // fail at time t. If t is zero, the deadline is infinite.
   127  func (p *MockPeer) SetWriteDeadline(t time.Time) error {
   128  	if t.IsZero() {
   129  		p.writeDeadline = nil
   130  		return nil
   131  	}
   132  
   133  	duration := time.Until(t)
   134  	p.writeDeadline = time.After(duration)
   135  
   136  	return nil
   137  }
   138  
   139  // SetReadDeadline initializes a timer that will cause any pending reads to fail
   140  // at time t. If t is zero, the deadline is infinite.
   141  func (p *MockPeer) SetReadDeadline(t time.Time) error {
   142  	if t.IsZero() {
   143  		p.readDeadline = nil
   144  		return nil
   145  	}
   146  
   147  	duration := time.Until(t)
   148  	p.readDeadline = time.After(duration)
   149  
   150  	return nil
   151  }
   152  
   153  // RemotePub returns the public key of the remote peer.
   154  func (p *MockPeer) RemotePub() *secp256k1.PublicKey {
   155  	return p.remotePub
   156  }
   157  
   158  // RemoteAddr returns the net address of the remote peer.
   159  func (p *MockPeer) RemoteAddr() net.Addr {
   160  	return p.remoteAddr
   161  }
   162  
   163  // LocalAddr returns the local net address of the peer.
   164  func (p *MockPeer) LocalAddr() net.Addr {
   165  	return p.localAddr
   166  }
   167  
   168  // Read is not implemented.
   169  func (p *MockPeer) Read(dst []byte) (int, error) {
   170  	panic("not implemented")
   171  }
   172  
   173  // SetDeadline is not implemented.
   174  func (p *MockPeer) SetDeadline(t time.Time) error {
   175  	panic("not implemented")
   176  }
   177  
   178  // Compile-time constraint ensuring the MockPeer implements the wserver.Peer
   179  // interface.
   180  var _ wtserver.Peer = (*MockPeer)(nil)
   181  
   182  // Compile-time constraint ensuring the MockPeer implements the net.Conn
   183  // interface.
   184  var _ net.Conn = (*MockPeer)(nil)