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  }