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)