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 }