github.com/igggame/nebulas-go@v2.1.0+incompatible/net/neb_message.go (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package net
    20  
    21  import (
    22  	"bytes"
    23  	"errors"
    24  	"hash/crc32"
    25  	"time"
    26  
    27  	"github.com/golang/snappy"
    28  	byteutils "github.com/nebulasio/go-nebulas/util/byteutils"
    29  	"github.com/nebulasio/go-nebulas/util/logging"
    30  	"github.com/sirupsen/logrus"
    31  )
    32  
    33  /*
    34  NebMessage defines protocol in Nebulas, we define our own wire protocol, as the following:
    35  
    36   0               1               2               3              (bytes)
    37   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    38  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    39  |                         Magic Number                          |
    40  +---------------------------------------------------------------+
    41  |                         Chain ID                              |
    42  +-----------------------------------------------+---------------+
    43  |                         Reserved              |   Version     |
    44  +-----------------------------------------------+---------------+
    45  |                                                               |
    46  +                                                               +
    47  |                         Message Name                          |
    48  +                                                               +
    49  |                                                               |
    50  +---------------------------------------------------------------+
    51  |                         Data Length                           |
    52  +---------------------------------------------------------------+
    53  |                         Data Checksum                         |
    54  +---------------------------------------------------------------+
    55  |                         Header Checksum                       |
    56  |---------------------------------------------------------------+
    57  |                                                               |
    58  +                         Data                                  +
    59  .                                                               .
    60  |                                                               |
    61  +---------------------------------------------------------------+
    62  */
    63  // const
    64  const (
    65  	NebMessageMagicNumberEndIdx    = 4
    66  	NebMessageChainIDEndIdx        = 8
    67  	NebMessageReservedEndIdx       = 11
    68  	NebMessageVersionIndex         = 11
    69  	NebMessageVersionEndIdx        = 12
    70  	NebMessageNameEndIdx           = 24
    71  	NebMessageDataLengthEndIdx     = 28
    72  	NebMessageDataCheckSumEndIdx   = 32
    73  	NebMessageHeaderCheckSumEndIdx = 36
    74  	NebMessageHeaderLength         = 36
    75  
    76  	// Consider that a block is too large in sync.
    77  	MaxNebMessageDataLength = 512 * 1024 * 1024 // 512m.
    78  	MaxNebMessageNameLength = 24 - 12           // 12.
    79  
    80  	DefaultReservedFlag           = 0x0
    81  	ReservedCompressionEnableFlag = 0x80
    82  	ReservedCompressionClientFlag = 0x1
    83  )
    84  
    85  // Error types
    86  var (
    87  	MagicNumber     = []byte{0x4e, 0x45, 0x42, 0x31}
    88  	DefaultReserved = []byte{DefaultReservedFlag, DefaultReservedFlag, DefaultReservedFlag}
    89  	CurrentReserved = []byte{DefaultReservedFlag | ReservedCompressionEnableFlag, DefaultReservedFlag, DefaultReservedFlag}
    90  
    91  	ErrInsufficientMessageHeaderLength = errors.New("insufficient message header length")
    92  	ErrInsufficientMessageDataLength   = errors.New("insufficient message data length")
    93  	ErrInvalidMagicNumber              = errors.New("invalid magic number")
    94  	ErrInvalidHeaderCheckSum           = errors.New("invalid header checksum")
    95  	ErrInvalidDataCheckSum             = errors.New("invalid data checksum")
    96  	ErrExceedMaxDataLength             = errors.New("exceed max data length")
    97  	ErrExceedMaxMessageNameLength      = errors.New("exceed max message name length")
    98  	ErrUncompressMessageFailed         = errors.New("uncompress message failed")
    99  )
   100  
   101  //NebMessage struct
   102  type NebMessage struct {
   103  	content     []byte
   104  	messageName string
   105  
   106  	// debug fields.
   107  	sendMessageAt  int64
   108  	writeMessageAt int64
   109  }
   110  
   111  // MagicNumber return magicNumber
   112  func (message *NebMessage) MagicNumber() []byte {
   113  	return message.content[0:NebMessageMagicNumberEndIdx]
   114  }
   115  
   116  // ChainID return chainID
   117  func (message *NebMessage) ChainID() uint32 {
   118  	return byteutils.Uint32(message.content[NebMessageMagicNumberEndIdx:NebMessageChainIDEndIdx])
   119  }
   120  
   121  // Reserved return reserved
   122  func (message *NebMessage) Reserved() []byte {
   123  	return message.content[NebMessageChainIDEndIdx:NebMessageReservedEndIdx]
   124  }
   125  
   126  // Version return version
   127  func (message *NebMessage) Version() byte {
   128  	return message.content[NebMessageVersionIndex]
   129  }
   130  
   131  // MessageName return message name
   132  func (message *NebMessage) MessageName() string {
   133  	if message.messageName == "" {
   134  		data := message.content[NebMessageVersionEndIdx:NebMessageNameEndIdx]
   135  		pos := bytes.IndexByte(data, 0)
   136  		if pos != -1 {
   137  			message.messageName = string(data[0:pos])
   138  		} else {
   139  			message.messageName = string(data)
   140  		}
   141  	}
   142  	return message.messageName
   143  }
   144  
   145  // DataLength return dataLength
   146  func (message *NebMessage) DataLength() uint32 {
   147  	return byteutils.Uint32(message.content[NebMessageNameEndIdx:NebMessageDataLengthEndIdx])
   148  }
   149  
   150  // DataCheckSum return data checkSum
   151  func (message *NebMessage) DataCheckSum() uint32 {
   152  	return byteutils.Uint32(message.content[NebMessageDataLengthEndIdx:NebMessageDataCheckSumEndIdx])
   153  }
   154  
   155  // HeaderCheckSum return header checkSum
   156  func (message *NebMessage) HeaderCheckSum() uint32 {
   157  	return byteutils.Uint32(message.content[NebMessageDataCheckSumEndIdx:NebMessageHeaderCheckSumEndIdx])
   158  }
   159  
   160  // HeaderWithoutCheckSum return header without checkSum
   161  func (message *NebMessage) HeaderWithoutCheckSum() []byte {
   162  	return message.content[:NebMessageDataCheckSumEndIdx]
   163  }
   164  
   165  // Data return data
   166  func (message *NebMessage) Data() ([]byte, error) {
   167  	reserved := message.Reserved()
   168  	data := message.content[NebMessageHeaderLength:]
   169  	if (reserved[0] & ReservedCompressionEnableFlag) > 0 {
   170  		var err error
   171  		data, err = snappy.Decode(nil, data)
   172  		if err != nil {
   173  			return nil, ErrUncompressMessageFailed
   174  		}
   175  	}
   176  	return data, nil
   177  }
   178  
   179  // OriginalData return original data
   180  func (message *NebMessage) OriginalData() []byte {
   181  	return message.content[NebMessageHeaderLength:]
   182  }
   183  
   184  // Content return message content
   185  func (message *NebMessage) Content() []byte {
   186  	return message.content
   187  }
   188  
   189  // Length return message Length
   190  func (message *NebMessage) Length() uint64 {
   191  	return uint64(len(message.content))
   192  }
   193  
   194  // NewNebMessage new neb message
   195  func NewNebMessage(chainID uint32, reserved []byte, version byte, messageName string, data []byte) (*NebMessage, error) {
   196  	// Process message compression
   197  	if (reserved[2] != ReservedCompressionClientFlag) && ((reserved[0] & ReservedCompressionEnableFlag) > 0) {
   198  		data = snappy.Encode(nil, data)
   199  	}
   200  
   201  	if len(data) > MaxNebMessageDataLength {
   202  		logging.VLog().WithFields(logrus.Fields{
   203  			"messageName": messageName,
   204  			"dataLength":  len(data),
   205  			"limits":      MaxNebMessageDataLength,
   206  		}).Debug("Exceeded max data length.")
   207  		return nil, ErrExceedMaxDataLength
   208  	}
   209  
   210  	if len(messageName) > MaxNebMessageNameLength {
   211  		logging.VLog().WithFields(logrus.Fields{
   212  			"messageName":      messageName,
   213  			"len(messageName)": len(messageName),
   214  			"limits":           MaxNebMessageNameLength,
   215  		}).Debug("Exceeded max message name length.")
   216  		return nil, ErrExceedMaxMessageNameLength
   217  	}
   218  
   219  	dataCheckSum := crc32.ChecksumIEEE(data)
   220  
   221  	message := &NebMessage{
   222  		content: make([]byte, NebMessageHeaderLength+len(data)),
   223  	}
   224  
   225  	// copy fields.
   226  	copy(message.content[0:NebMessageMagicNumberEndIdx], MagicNumber)
   227  	copy(message.content[NebMessageMagicNumberEndIdx:NebMessageChainIDEndIdx], byteutils.FromUint32(chainID))
   228  	copy(message.content[NebMessageChainIDEndIdx:NebMessageReservedEndIdx], reserved)
   229  	message.content[NebMessageVersionIndex] = version
   230  	copy(message.content[NebMessageVersionEndIdx:NebMessageNameEndIdx], []byte(messageName))
   231  	copy(message.content[NebMessageNameEndIdx:NebMessageDataLengthEndIdx], byteutils.FromUint32(uint32(len(data))))
   232  	copy(message.content[NebMessageDataLengthEndIdx:NebMessageDataCheckSumEndIdx], byteutils.FromUint32(dataCheckSum))
   233  
   234  	// header checksum.
   235  	headerCheckSum := crc32.ChecksumIEEE(message.HeaderWithoutCheckSum())
   236  	copy(message.content[NebMessageDataCheckSumEndIdx:NebMessageHeaderCheckSumEndIdx], byteutils.FromUint32(headerCheckSum))
   237  
   238  	// copy data.
   239  	copy(message.content[NebMessageHeaderCheckSumEndIdx:], data)
   240  
   241  	return message, nil
   242  }
   243  
   244  // ParseNebMessage parse neb message
   245  func ParseNebMessage(data []byte) (*NebMessage, error) {
   246  	if len(data) < NebMessageHeaderLength {
   247  		return nil, ErrInsufficientMessageHeaderLength
   248  	}
   249  
   250  	message := &NebMessage{
   251  		content: make([]byte, NebMessageHeaderLength),
   252  	}
   253  	copy(message.content, data)
   254  
   255  	if err := message.VerifyHeader(); err != nil {
   256  		return nil, err
   257  	}
   258  
   259  	return message, nil
   260  }
   261  
   262  // ParseMessageData parse neb message data
   263  func (message *NebMessage) ParseMessageData(data []byte) error {
   264  	if uint32(len(data)) < message.DataLength() {
   265  		return ErrInsufficientMessageDataLength
   266  	}
   267  
   268  	message.content = append(message.content, data[:message.DataLength()]...)
   269  	return message.VerifyData()
   270  }
   271  
   272  // VerifyHeader verify message header
   273  func (message *NebMessage) VerifyHeader() error {
   274  	if !byteutils.Equal(MagicNumber, message.MagicNumber()) {
   275  		logging.VLog().WithFields(logrus.Fields{
   276  			"expect": MagicNumber,
   277  			"actual": message.MagicNumber(),
   278  			"err":    "invalid magic number",
   279  		}).Debug("Failed to verify header.")
   280  		return ErrInvalidMagicNumber
   281  	}
   282  
   283  	expectedCheckSum := crc32.ChecksumIEEE(message.HeaderWithoutCheckSum())
   284  	if expectedCheckSum != message.HeaderCheckSum() {
   285  		logging.VLog().WithFields(logrus.Fields{
   286  			"expect": expectedCheckSum,
   287  			"actual": message.HeaderCheckSum(),
   288  			"err":    "invalid header checksum",
   289  		}).Debug("Failed to verify header.")
   290  		return ErrInvalidHeaderCheckSum
   291  	}
   292  
   293  	if message.DataLength() > MaxNebMessageDataLength {
   294  		logging.VLog().WithFields(logrus.Fields{
   295  			"messageName": message.MessageName(),
   296  			"dataLength":  message.DataLength(),
   297  			"limit":       MaxNebMessageDataLength,
   298  			"err":         "exceeded max data length",
   299  		}).Debug("Failed to verify header.")
   300  		return ErrExceedMaxDataLength
   301  	}
   302  
   303  	return nil
   304  }
   305  
   306  // VerifyData verify message data
   307  func (message *NebMessage) VerifyData() error {
   308  	expectedCheckSum := crc32.ChecksumIEEE(message.OriginalData())
   309  	if expectedCheckSum != message.DataCheckSum() {
   310  		logging.VLog().WithFields(logrus.Fields{
   311  			"expect": expectedCheckSum,
   312  			"actual": message.DataCheckSum(),
   313  			"err":    "invalid data checksum",
   314  		}).Debug("Failed to verify data")
   315  		return ErrInvalidDataCheckSum
   316  	}
   317  	return nil
   318  }
   319  
   320  // FlagSendMessageAt flag of send message time
   321  func (message *NebMessage) FlagSendMessageAt() {
   322  	message.sendMessageAt = time.Now().UnixNano()
   323  }
   324  
   325  // FlagWriteMessageAt flag of write message time
   326  func (message *NebMessage) FlagWriteMessageAt() {
   327  	message.writeMessageAt = time.Now().UnixNano()
   328  }
   329  
   330  // LatencyFromSendToWrite latency from sendMessage to writeMessage
   331  func (message *NebMessage) LatencyFromSendToWrite() int64 {
   332  	if message.sendMessageAt == 0 {
   333  		return -1
   334  	} else if message.writeMessageAt == 0 {
   335  		message.FlagWriteMessageAt()
   336  	}
   337  
   338  	// convert from nano to millisecond.
   339  	return (message.writeMessageAt - message.sendMessageAt) / int64(time.Millisecond)
   340  }