github.com/evdatsion/aphelion-dpos-bft@v0.32.1/p2p/peer_test.go (about) 1 package p2p 2 3 import ( 4 "fmt" 5 golog "log" 6 "net" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/evdatsion/aphelion-dpos-bft/crypto" 14 "github.com/evdatsion/aphelion-dpos-bft/crypto/ed25519" 15 cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common" 16 "github.com/evdatsion/aphelion-dpos-bft/libs/log" 17 18 "github.com/evdatsion/aphelion-dpos-bft/config" 19 tmconn "github.com/evdatsion/aphelion-dpos-bft/p2p/conn" 20 ) 21 22 func TestPeerBasic(t *testing.T) { 23 assert, require := assert.New(t), require.New(t) 24 25 // simulate remote peer 26 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 27 rp.Start() 28 defer rp.Stop() 29 30 p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), cfg, tmconn.DefaultMConnConfig()) 31 require.Nil(err) 32 33 err = p.Start() 34 require.Nil(err) 35 defer p.Stop() 36 37 assert.True(p.IsRunning()) 38 assert.True(p.IsOutbound()) 39 assert.False(p.IsPersistent()) 40 p.persistent = true 41 assert.True(p.IsPersistent()) 42 assert.Equal(rp.Addr().DialString(), p.RemoteAddr().String()) 43 assert.Equal(rp.ID(), p.ID()) 44 } 45 46 func TestPeerSend(t *testing.T) { 47 assert, require := assert.New(t), require.New(t) 48 49 config := cfg 50 51 // simulate remote peer 52 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: config} 53 rp.Start() 54 defer rp.Stop() 55 56 p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), config, tmconn.DefaultMConnConfig()) 57 require.Nil(err) 58 59 err = p.Start() 60 require.Nil(err) 61 62 defer p.Stop() 63 64 assert.True(p.CanSend(testCh)) 65 assert.True(p.Send(testCh, []byte("Asylum"))) 66 } 67 68 func createOutboundPeerAndPerformHandshake( 69 addr *NetAddress, 70 config *config.P2PConfig, 71 mConfig tmconn.MConnConfig, 72 ) (*peer, error) { 73 chDescs := []*tmconn.ChannelDescriptor{ 74 {ID: testCh, Priority: 1}, 75 } 76 reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true)} 77 pk := ed25519.GenPrivKey() 78 pc, err := testOutboundPeerConn(addr, config, false, pk) 79 if err != nil { 80 return nil, err 81 } 82 timeout := 1 * time.Second 83 ourNodeInfo := testNodeInfo(addr.ID, "host_peer") 84 peerNodeInfo, err := handshake(pc.conn, timeout, ourNodeInfo) 85 if err != nil { 86 return nil, err 87 } 88 89 p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, chDescs, func(p Peer, r interface{}) {}) 90 p.SetLogger(log.TestingLogger().With("peer", addr)) 91 return p, nil 92 } 93 94 func testDial(addr *NetAddress, cfg *config.P2PConfig) (net.Conn, error) { 95 if cfg.TestDialFail { 96 return nil, fmt.Errorf("dial err (peerConfig.DialFail == true)") 97 } 98 99 conn, err := addr.DialTimeout(cfg.DialTimeout) 100 if err != nil { 101 return nil, err 102 } 103 return conn, nil 104 } 105 106 func testOutboundPeerConn( 107 addr *NetAddress, 108 config *config.P2PConfig, 109 persistent bool, 110 ourNodePrivKey crypto.PrivKey, 111 ) (peerConn, error) { 112 113 var pc peerConn 114 conn, err := testDial(addr, config) 115 if err != nil { 116 return pc, cmn.ErrorWrap(err, "Error creating peer") 117 } 118 119 pc, err = testPeerConn(conn, config, true, persistent, ourNodePrivKey, addr) 120 if err != nil { 121 if cerr := conn.Close(); cerr != nil { 122 return pc, cmn.ErrorWrap(err, cerr.Error()) 123 } 124 return pc, err 125 } 126 127 // ensure dialed ID matches connection ID 128 if addr.ID != pc.ID() { 129 if cerr := conn.Close(); cerr != nil { 130 return pc, cmn.ErrorWrap(err, cerr.Error()) 131 } 132 return pc, ErrSwitchAuthenticationFailure{addr, pc.ID()} 133 } 134 135 return pc, nil 136 } 137 138 type remotePeer struct { 139 PrivKey crypto.PrivKey 140 Config *config.P2PConfig 141 addr *NetAddress 142 channels cmn.HexBytes 143 listenAddr string 144 listener net.Listener 145 } 146 147 func (rp *remotePeer) Addr() *NetAddress { 148 return rp.addr 149 } 150 151 func (rp *remotePeer) ID() ID { 152 return PubKeyToID(rp.PrivKey.PubKey()) 153 } 154 155 func (rp *remotePeer) Start() { 156 if rp.listenAddr == "" { 157 rp.listenAddr = "127.0.0.1:0" 158 } 159 160 l, e := net.Listen("tcp", rp.listenAddr) // any available address 161 if e != nil { 162 golog.Fatalf("net.Listen tcp :0: %+v", e) 163 } 164 rp.listener = l 165 rp.addr = NewNetAddress(PubKeyToID(rp.PrivKey.PubKey()), l.Addr()) 166 if rp.channels == nil { 167 rp.channels = []byte{testCh} 168 } 169 go rp.accept() 170 } 171 172 func (rp *remotePeer) Stop() { 173 rp.listener.Close() 174 } 175 176 func (rp *remotePeer) Dial(addr *NetAddress) (net.Conn, error) { 177 conn, err := addr.DialTimeout(1 * time.Second) 178 if err != nil { 179 return nil, err 180 } 181 pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey) 182 if err != nil { 183 return nil, err 184 } 185 _, err = handshake(pc.conn, time.Second, rp.nodeInfo()) 186 if err != nil { 187 return nil, err 188 } 189 return conn, err 190 } 191 192 func (rp *remotePeer) accept() { 193 conns := []net.Conn{} 194 195 for { 196 conn, err := rp.listener.Accept() 197 if err != nil { 198 golog.Printf("Failed to accept conn: %+v", err) 199 for _, conn := range conns { 200 _ = conn.Close() 201 } 202 return 203 } 204 205 pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey) 206 if err != nil { 207 golog.Fatalf("Failed to create a peer: %+v", err) 208 } 209 210 _, err = handshake(pc.conn, time.Second, rp.nodeInfo()) 211 if err != nil { 212 golog.Fatalf("Failed to perform handshake: %+v", err) 213 } 214 215 conns = append(conns, conn) 216 } 217 } 218 219 func (rp *remotePeer) nodeInfo() NodeInfo { 220 return DefaultNodeInfo{ 221 ProtocolVersion: defaultProtocolVersion, 222 ID_: rp.Addr().ID, 223 ListenAddr: rp.listener.Addr().String(), 224 Network: "testing", 225 Version: "1.2.3-rc0-deadbeef", 226 Channels: rp.channels, 227 Moniker: "remote_peer", 228 } 229 }