github.com/aergoio/aergo@v1.3.1/p2p/p2pcommon/handshake.go (about) 1 /* 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 //go:generate mockgen -source=handshake.go -package=p2pmock -destination=../p2pmock/mock_handshake.go 6 package p2pcommon 7 8 import ( 9 "context" 10 "encoding/binary" 11 "github.com/aergoio/aergo/types" 12 "io" 13 "time" 14 ) 15 16 17 // HSHandlerFactory is creator of HSHandler 18 type HSHandlerFactory interface { 19 CreateHSHandler(legacy bool, outbound bool, pid types.PeerID) HSHandler 20 } 21 22 // HSHandler handles whole process of connect, handshake, create of remote Peer 23 type HSHandler interface { 24 // Handle peer handshake till ttl, and return msgrw for this connection, and status of remote peer. 25 Handle(s io.ReadWriteCloser, ttl time.Duration) (MsgReadWriter, *types.Status, error) 26 } 27 28 type VersionedManager interface { 29 FindBestP2PVersion(versions []P2PVersion) P2PVersion 30 GetVersionedHandshaker(version P2PVersion, peerID types.PeerID, rwc io.ReadWriteCloser) (VersionedHandshaker, error) 31 } 32 33 // VersionedHandshaker do handshake related to chain, and return msgreadwriter for a protocol version. 34 // It is used inside HSHandler 35 type VersionedHandshaker interface { 36 DoForOutbound(ctx context.Context) (*types.Status, error) 37 DoForInbound(ctx context.Context) (*types.Status, error) 38 GetMsgRW() MsgReadWriter 39 } 40 41 // HSHeader is legacy type of data which peer send first to listening peer in wire handshake 42 type HSHeader struct { 43 Magic uint32 44 Version P2PVersion 45 } 46 47 func (h HSHeader) Marshal() []byte { 48 b := make([]byte, V030HSHeaderLength) 49 binary.BigEndian.PutUint32(b, h.Magic) 50 binary.BigEndian.PutUint32(b[4:], uint32(h.Version)) 51 return b 52 } 53 54 func (h *HSHeader) Unmarshal(b []byte) { 55 h.Magic = binary.BigEndian.Uint32(b) 56 h.Version = P2PVersion(binary.BigEndian.Uint32(b[4:])) 57 } 58 59 // HSHeadReq is data which peer send first to listening peer in wire handshake 60 type HSHeadReq struct { 61 Magic uint32 62 // Versions are p2p versions which the connecting peer can support. 63 Versions []P2PVersion 64 } 65 66 func (h HSHeadReq) Marshal() []byte { 67 verCount := len(h.Versions) 68 b := make([]byte, HSMagicLength+HSVerCntLength+HSVersionLength*verCount) 69 offset := 0 70 binary.BigEndian.PutUint32(b[offset:], h.Magic) 71 offset += HSMagicLength 72 binary.BigEndian.PutUint32(b[offset:], uint32(verCount)) 73 offset += HSVerCntLength 74 for _, version := range h.Versions { 75 binary.BigEndian.PutUint32(b[offset:], version.Uint32()) 76 offset += HSVersionLength 77 } 78 return b 79 } 80 81 // HSHeadResp is data which listening peer send back to connecting peer as response 82 type HSHeadResp struct { 83 // Magic will be same as the magic in HSHeadReq if wire handshake is successful, or 0 if not. 84 Magic uint32 85 // RespCode is different meaning by value of Magic. It is p2p version which listening peer will use, if wire handshake is successful, or errCode otherwise. 86 RespCode uint32 87 } 88 89 func (h HSHeadResp) Marshal() []byte { 90 b := make([]byte, V030HSHeaderLength) 91 binary.BigEndian.PutUint32(b, h.Magic) 92 binary.BigEndian.PutUint32(b[4:], h.RespCode) 93 return b 94 } 95 96 func (h *HSHeadResp) Unmarshal(b []byte) { 97 h.Magic = binary.BigEndian.Uint32(b) 98 h.RespCode = binary.BigEndian.Uint32(b[4:]) 99 }