github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/tendermint/p2p/conn/connection.go (about) 1 package conn 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/binary" 7 "runtime/debug" 8 9 "fmt" 10 "io" 11 "math" 12 "net" 13 "reflect" 14 "sync" 15 "sync/atomic" 16 "time" 17 18 "github.com/pkg/errors" 19 20 amino "github.com/tendermint/go-amino" 21 22 flow "github.com/fibonacci-chain/fbc/libs/tendermint/libs/flowrate" 23 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 24 tmmath "github.com/fibonacci-chain/fbc/libs/tendermint/libs/math" 25 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/service" 26 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/timer" 27 ) 28 29 const ( 30 defaultMaxPacketMsgPayloadSize = 1024 31 32 numBatchPacketMsgs = 10 33 minReadBufferSize = 1024 34 minWriteBufferSize = 65536 35 updateStats = 2 * time.Second 36 37 // some of these defaults are written in the user config 38 // flushThrottle, sendRate, recvRate 39 // TODO: remove values present in config 40 defaultFlushThrottle = 100 * time.Millisecond 41 42 defaultSendQueueCapacity = 1 43 defaultRecvBufferCapacity = 4096 44 defaultRecvMessageCapacity = 22020096 // 21MB 45 defaultSendRate = int64(512000) // 500KB/s 46 defaultRecvRate = int64(512000) // 500KB/s 47 defaultSendTimeout = 10 * time.Second 48 defaultPingInterval = 60 * time.Second 49 defaultPongTimeout = 45 * time.Second 50 ) 51 52 type logData struct { 53 Params [6]interface{} 54 Bytes bytesHexStringer 55 Packet PacketMsg 56 } 57 58 var logDataPool = &sync.Pool{ 59 New: func() interface{} { 60 return &logData{} 61 }, 62 } 63 64 type receiveCbFunc func(chID byte, msgBytes []byte) 65 type errorCbFunc func(interface{}) 66 67 type bytesHexStringer []byte 68 69 func (b bytesHexStringer) String() string { 70 return fmt.Sprintf("%X", []byte(b)) 71 } 72 73 /* 74 Each peer has one `MConnection` (multiplex connection) instance. 75 76 __multiplex__ *noun* a system or signal involving simultaneous transmission of 77 several messages along a single channel of communication. 78 79 Each `MConnection` handles message transmission on multiple abstract communication 80 `Channel`s. Each channel has a globally unique byte id. 81 The byte id and the relative priorities of each `Channel` are configured upon 82 initialization of the connection. 83 84 There are two methods for sending messages: 85 86 func (m MConnection) Send(chID byte, msgBytes []byte) bool {} 87 func (m MConnection) TrySend(chID byte, msgBytes []byte}) bool {} 88 89 `Send(chID, msgBytes)` is a blocking call that waits until `msg` is 90 successfully queued for the channel with the given id byte `chID`, or until the 91 request times out. The message `msg` is serialized using Go-Amino. 92 93 `TrySend(chID, msgBytes)` is a nonblocking call that returns false if the 94 channel's queue is full. 95 96 Inbound message bytes are handled with an onReceive callback function. 97 */ 98 type MConnection struct { 99 service.BaseService 100 101 conn net.Conn 102 bufConnReader *bufio.Reader 103 bufConnWriter *bufio.Writer 104 sendMonitor *flow.Monitor 105 recvMonitor *flow.Monitor 106 send chan struct{} 107 pong chan struct{} 108 channels []*Channel 109 channelsIdx map[byte]*Channel 110 onReceive receiveCbFunc 111 onError errorCbFunc 112 errored uint32 113 config MConnConfig 114 115 // Closing quitSendRoutine will cause the sendRoutine to eventually quit. 116 // doneSendRoutine is closed when the sendRoutine actually quits. 117 quitSendRoutine chan struct{} 118 doneSendRoutine chan struct{} 119 120 // Closing quitRecvRouting will cause the recvRouting to eventually quit. 121 quitRecvRoutine chan struct{} 122 123 // used to ensure FlushStop and OnStop 124 // are safe to call concurrently. 125 stopMtx sync.Mutex 126 127 flushTimer *timer.ThrottleTimer // flush writes as necessary but throttled. 128 pingTimer *time.Ticker // send pings periodically 129 130 // close conn if pong is not received in pongTimeout 131 pongTimer *time.Timer 132 pongTimeoutCh chan bool // true - timeout, false - peer sent pong 133 134 chStatsTimer *time.Ticker // update channel stats periodically 135 136 created time.Time // time of creation 137 138 _maxPacketMsgSize int 139 } 140 141 // MConnConfig is a MConnection configuration. 142 type MConnConfig struct { 143 SendRate int64 `mapstructure:"send_rate"` 144 RecvRate int64 `mapstructure:"recv_rate"` 145 146 // Maximum payload size 147 MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"` 148 149 // Interval to flush writes (throttled) 150 FlushThrottle time.Duration `mapstructure:"flush_throttle"` 151 152 // Interval to send pings 153 PingInterval time.Duration `mapstructure:"ping_interval"` 154 155 // Maximum wait time for pongs 156 PongTimeout time.Duration `mapstructure:"pong_timeout"` 157 } 158 159 // DefaultMConnConfig returns the default config. 160 func DefaultMConnConfig() MConnConfig { 161 return MConnConfig{ 162 SendRate: defaultSendRate, 163 RecvRate: defaultRecvRate, 164 MaxPacketMsgPayloadSize: defaultMaxPacketMsgPayloadSize, 165 FlushThrottle: defaultFlushThrottle, 166 PingInterval: defaultPingInterval, 167 PongTimeout: defaultPongTimeout, 168 } 169 } 170 171 // NewMConnection wraps net.Conn and creates multiplex connection 172 func NewMConnection( 173 conn net.Conn, 174 chDescs []*ChannelDescriptor, 175 onReceive receiveCbFunc, 176 onError errorCbFunc, 177 ) *MConnection { 178 return NewMConnectionWithConfig( 179 conn, 180 chDescs, 181 onReceive, 182 onError, 183 DefaultMConnConfig()) 184 } 185 186 // NewMConnectionWithConfig wraps net.Conn and creates multiplex connection with a config 187 func NewMConnectionWithConfig( 188 conn net.Conn, 189 chDescs []*ChannelDescriptor, 190 onReceive receiveCbFunc, 191 onError errorCbFunc, 192 config MConnConfig, 193 ) *MConnection { 194 if config.PongTimeout >= config.PingInterval { 195 panic("pongTimeout must be less than pingInterval (otherwise, next ping will reset pong timer)") 196 } 197 198 mconn := &MConnection{ 199 conn: conn, 200 bufConnReader: bufio.NewReaderSize(conn, minReadBufferSize), 201 bufConnWriter: bufio.NewWriterSize(conn, minWriteBufferSize), 202 sendMonitor: flow.New(0, 0), 203 recvMonitor: flow.New(0, 0), 204 send: make(chan struct{}, 1), 205 pong: make(chan struct{}, 1), 206 onReceive: onReceive, 207 onError: onError, 208 config: config, 209 created: time.Now(), 210 } 211 212 // Create channels 213 var channelsIdx = map[byte]*Channel{} 214 var channels = []*Channel{} 215 216 for _, desc := range chDescs { 217 channel := newChannel(mconn, *desc) 218 channelsIdx[channel.desc.ID] = channel 219 channels = append(channels, channel) 220 } 221 mconn.channels = channels 222 mconn.channelsIdx = channelsIdx 223 224 mconn.BaseService = *service.NewBaseService(nil, "MConnection", mconn) 225 226 // maxPacketMsgSize() is a bit heavy, so call just once 227 mconn._maxPacketMsgSize = mconn.maxPacketMsgSize() 228 229 return mconn 230 } 231 232 func (c *MConnection) SetLogger(l log.Logger) { 233 c.BaseService.SetLogger(l) 234 for _, ch := range c.channels { 235 ch.SetLogger(l) 236 } 237 } 238 239 // OnStart implements BaseService 240 func (c *MConnection) OnStart() error { 241 if err := c.BaseService.OnStart(); err != nil { 242 return err 243 } 244 c.flushTimer = timer.NewThrottleTimer("flush", c.config.FlushThrottle) 245 c.pingTimer = time.NewTicker(c.config.PingInterval) 246 c.pongTimeoutCh = make(chan bool, 1) 247 c.chStatsTimer = time.NewTicker(updateStats) 248 c.quitSendRoutine = make(chan struct{}) 249 c.doneSendRoutine = make(chan struct{}) 250 c.quitRecvRoutine = make(chan struct{}) 251 go c.sendRoutine() 252 go c.recvRoutine() 253 return nil 254 } 255 256 // stopServices stops the BaseService and timers and closes the quitSendRoutine. 257 // if the quitSendRoutine was already closed, it returns true, otherwise it returns false. 258 // It uses the stopMtx to ensure only one of FlushStop and OnStop can do this at a time. 259 func (c *MConnection) stopServices() (alreadyStopped bool) { 260 c.stopMtx.Lock() 261 defer c.stopMtx.Unlock() 262 263 select { 264 case <-c.quitSendRoutine: 265 // already quit 266 return true 267 default: 268 } 269 270 select { 271 case <-c.quitRecvRoutine: 272 // already quit 273 return true 274 default: 275 } 276 277 c.BaseService.OnStop() 278 c.flushTimer.Stop() 279 c.pingTimer.Stop() 280 c.chStatsTimer.Stop() 281 282 // inform the recvRouting that we are shutting down 283 close(c.quitRecvRoutine) 284 close(c.quitSendRoutine) 285 return false 286 } 287 288 // FlushStop replicates the logic of OnStop. 289 // It additionally ensures that all successful 290 // .Send() calls will get flushed before closing 291 // the connection. 292 func (c *MConnection) FlushStop() { 293 if c.stopServices() { 294 return 295 } 296 297 // this block is unique to FlushStop 298 { 299 // wait until the sendRoutine exits 300 // so we dont race on calling sendSomePacketMsgs 301 <-c.doneSendRoutine 302 303 // Send and flush all pending msgs. 304 // Since sendRoutine has exited, we can call this 305 // safely 306 eof := c.sendSomePacketMsgs() 307 for !eof { 308 eof = c.sendSomePacketMsgs() 309 } 310 c.flush() 311 312 // Now we can close the connection 313 } 314 315 c.conn.Close() // nolint: errcheck 316 317 // We can't close pong safely here because 318 // recvRoutine may write to it after we've stopped. 319 // Though it doesn't need to get closed at all, 320 // we close it @ recvRoutine. 321 322 // c.Stop() 323 } 324 325 // OnStop implements BaseService 326 func (c *MConnection) OnStop() { 327 if c.stopServices() { 328 return 329 } 330 331 c.conn.Close() // nolint: errcheck 332 333 // We can't close pong safely here because 334 // recvRoutine may write to it after we've stopped. 335 // Though it doesn't need to get closed at all, 336 // we close it @ recvRoutine. 337 } 338 339 func (c *MConnection) String() string { 340 return fmt.Sprintf("MConn{%v}", c.conn.RemoteAddr()) 341 } 342 343 func (c *MConnection) flush() { 344 c.Logger.Debug("Flush", "conn", c) 345 err := c.bufConnWriter.Flush() 346 if err != nil { 347 c.Logger.Error("MConnection flush failed", "err", err) 348 } 349 } 350 351 // Catch panics, usually caused by remote disconnects. 352 func (c *MConnection) _recover() { 353 if r := recover(); r != nil { 354 c.Logger.Error("MConnection panicked", "err", r, "stack", string(debug.Stack())) 355 c.stopForError(errors.Errorf("recovered from panic: %v", r)) 356 } 357 } 358 359 func (c *MConnection) stopForError(r interface{}) { 360 c.Stop() 361 if atomic.CompareAndSwapUint32(&c.errored, 0, 1) { 362 if c.onError != nil { 363 c.onError(r) 364 } 365 } 366 } 367 368 func (c *MConnection) logSendData(msg string, chID byte, msgBytes []byte) { 369 logParams := logDataPool.Get().(*logData) 370 logParams.Bytes = msgBytes 371 params := &logParams.Params 372 params[0] = "channel" 373 params[1] = chID 374 params[2] = "conn" 375 params[3] = c 376 params[4] = "msgBytes" 377 params[5] = &logParams.Bytes 378 379 c.Logger.Debug(msg, logParams.Params[:]...) 380 logDataPool.Put(logParams) 381 } 382 383 // Queues a message to be sent to channel. 384 func (c *MConnection) Send(chID byte, msgBytes []byte) bool { 385 if !c.IsRunning() { 386 return false 387 } 388 389 c.logSendData("Send", chID, msgBytes) 390 391 // Send message to channel. 392 channel, ok := c.channelsIdx[chID] 393 if !ok { 394 c.Logger.Error(fmt.Sprintf("Cannot send bytes, unknown channel %X", chID)) 395 return false 396 } 397 398 success := channel.sendBytes(msgBytes) 399 if success { 400 // Wake up sendRoutine if necessary 401 select { 402 case c.send <- struct{}{}: 403 default: 404 } 405 } else { 406 c.logSendData("Send failed", chID, msgBytes) 407 } 408 return success 409 } 410 411 // Queues a message to be sent to channel. 412 // Nonblocking, returns true if successful. 413 func (c *MConnection) TrySend(chID byte, msgBytes []byte) bool { 414 if !c.IsRunning() { 415 return false 416 } 417 418 c.Logger.Debug("TrySend", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes)) 419 420 // Send message to channel. 421 channel, ok := c.channelsIdx[chID] 422 if !ok { 423 c.Logger.Error(fmt.Sprintf("Cannot send bytes, unknown channel %X", chID)) 424 return false 425 } 426 427 ok = channel.trySendBytes(msgBytes) 428 if ok { 429 // Wake up sendRoutine if necessary 430 select { 431 case c.send <- struct{}{}: 432 default: 433 } 434 } 435 436 return ok 437 } 438 439 // CanSend returns true if you can send more data onto the chID, false 440 // otherwise. Use only as a heuristic. 441 func (c *MConnection) CanSend(chID byte) bool { 442 if !c.IsRunning() { 443 return false 444 } 445 446 channel, ok := c.channelsIdx[chID] 447 if !ok { 448 c.Logger.Error(fmt.Sprintf("Unknown channel %X", chID)) 449 return false 450 } 451 return channel.canSend() 452 } 453 454 // sendRoutine polls for packets to send from channels. 455 func (c *MConnection) sendRoutine() { 456 defer c._recover() 457 458 FOR_LOOP: 459 for { 460 var _n int64 461 var err error 462 SELECTION: 463 select { 464 case <-c.flushTimer.Ch: 465 // NOTE: flushTimer.Set() must be called every time 466 // something is written to .bufConnWriter. 467 c.flush() 468 case <-c.chStatsTimer.C: 469 for _, channel := range c.channels { 470 channel.updateStats() 471 } 472 case <-c.pingTimer.C: 473 c.Logger.Debug("Send Ping") 474 _n, err = cdc.MarshalBinaryLengthPrefixedWriterWithRegiteredMarshaller(c.bufConnWriter, PacketPing{}) 475 if err != nil { 476 _n, err = cdc.MarshalBinaryLengthPrefixedWriter(c.bufConnWriter, PacketPing{}) 477 } 478 if err != nil { 479 break SELECTION 480 } 481 c.sendMonitor.Update(int(_n)) 482 c.Logger.Debug("Starting pong timer", "dur", c.config.PongTimeout) 483 c.pongTimer = time.AfterFunc(c.config.PongTimeout, func() { 484 select { 485 case c.pongTimeoutCh <- true: 486 default: 487 } 488 }) 489 c.flush() 490 case timeout := <-c.pongTimeoutCh: 491 if timeout { 492 c.Logger.Debug("Pong timeout") 493 err = errors.New("pong timeout") 494 } else { 495 c.stopPongTimer() 496 } 497 case <-c.pong: 498 c.Logger.Debug("Send Pong") 499 _n, err = cdc.MarshalBinaryLengthPrefixedWriterWithRegiteredMarshaller(c.bufConnWriter, PacketPong{}) 500 if err != nil { 501 _n, err = cdc.MarshalBinaryLengthPrefixedWriter(c.bufConnWriter, PacketPong{}) 502 } 503 if err != nil { 504 break SELECTION 505 } 506 c.sendMonitor.Update(int(_n)) 507 c.flush() 508 case <-c.quitSendRoutine: 509 break FOR_LOOP 510 case <-c.send: 511 // Send some PacketMsgs 512 eof := c.sendSomePacketMsgs() 513 if !eof { 514 // Keep sendRoutine awake. 515 select { 516 case c.send <- struct{}{}: 517 default: 518 } 519 } 520 } 521 522 if !c.IsRunning() { 523 break FOR_LOOP 524 } 525 if err != nil { 526 c.Logger.Error("Connection failed @ sendRoutine", "conn", c, "err", err) 527 c.stopForError(err) 528 break FOR_LOOP 529 } 530 } 531 532 // Cleanup 533 c.stopPongTimer() 534 close(c.doneSendRoutine) 535 } 536 537 // Returns true if messages from channels were exhausted. 538 // Blocks in accordance to .sendMonitor throttling. 539 func (c *MConnection) sendSomePacketMsgs() bool { 540 // Block until .sendMonitor says we can write. 541 // Once we're ready we send more than we asked for, 542 // but amortized it should even out. 543 c.sendMonitor.Limit(c._maxPacketMsgSize, atomic.LoadInt64(&c.config.SendRate), true) 544 545 // Now send some PacketMsgs. 546 for i := 0; i < numBatchPacketMsgs; i++ { 547 if c.sendPacketMsg() { 548 return true 549 } 550 } 551 return false 552 } 553 554 // Returns true if messages from channels were exhausted. 555 func (c *MConnection) sendPacketMsg() bool { 556 // Choose a channel to create a PacketMsg from. 557 // The chosen channel will be the one whose recentlySent/priority is the least. 558 var leastRatio float32 = math.MaxFloat32 559 var leastChannel *Channel 560 for _, channel := range c.channels { 561 // If nothing to send, skip this channel 562 if !channel.isSendPending() { 563 continue 564 } 565 // Get ratio, and keep track of lowest ratio. 566 ratio := float32(channel.recentlySent) / float32(channel.desc.Priority) 567 if ratio < leastRatio { 568 leastRatio = ratio 569 leastChannel = channel 570 } 571 } 572 573 // Nothing to send? 574 if leastChannel == nil { 575 return true 576 } 577 // c.Logger.Info("Found a msgPacket to send") 578 579 // Make & send a PacketMsg from this channel 580 _n, err := leastChannel.writePacketMsgTo(c.bufConnWriter) 581 if err != nil { 582 c.Logger.Error("Failed to write PacketMsg", "err", err) 583 c.stopForError(err) 584 return true 585 } 586 c.sendMonitor.Update(int(_n)) 587 c.flushTimer.Set() 588 return false 589 } 590 591 // recvRoutine reads PacketMsgs and reconstructs the message using the channels' "recving" buffer. 592 // After a whole message has been assembled, it's pushed to onReceive(). 593 // Blocks depending on how the connection is throttled. 594 // Otherwise, it never blocks. 595 func (c *MConnection) recvRoutine() { 596 defer c._recover() 597 598 var packetMsg PacketMsg 599 FOR_LOOP: 600 for { 601 // Block until .recvMonitor says we can read. 602 c.recvMonitor.Limit(c._maxPacketMsgSize, atomic.LoadInt64(&c.config.RecvRate), true) 603 604 // Peek into bufConnReader for debugging 605 /* 606 if numBytes := c.bufConnReader.Buffered(); numBytes > 0 { 607 bz, err := c.bufConnReader.Peek(tmmath.MinInt(numBytes, 100)) 608 if err == nil { 609 // return 610 } else { 611 c.Logger.Debug("Error peeking connection buffer", "err", err) 612 // return nil 613 } 614 c.Logger.Info("Peek connection buffer", "numBytes", numBytes, "bz", bz) 615 } 616 */ 617 618 // Read packet type 619 var packet Packet 620 var _n int64 621 var err error 622 // _n, err = cdc.UnmarshalBinaryLengthPrefixedReader(c.bufConnReader, &packet, int64(c._maxPacketMsgSize)) 623 packet, _n, err = unmarshalPacketFromAminoReader(c.bufConnReader, int64(c._maxPacketMsgSize), &packetMsg) 624 c.recvMonitor.Update(int(_n)) 625 626 if err != nil { 627 // stopServices was invoked and we are shutting down 628 // receiving is excpected to fail since we will close the connection 629 select { 630 case <-c.quitRecvRoutine: 631 break FOR_LOOP 632 default: 633 } 634 635 if c.IsRunning() { 636 if err == io.EOF { 637 c.Logger.Info("Connection is closed @ recvRoutine (likely by the other side)", "conn", c) 638 } else { 639 c.Logger.Error("Connection failed @ recvRoutine (reading byte)", "conn", c, "err", err) 640 } 641 c.stopForError(err) 642 } 643 break FOR_LOOP 644 } 645 646 // Read more depending on packet type. 647 switch pkt := packet.(type) { 648 case PacketPing: 649 // TODO: prevent abuse, as they cause flush()'s. 650 // https://github.com/tendermint/tendermint/issues/1190 651 c.Logger.Debug("Receive Ping") 652 select { 653 case c.pong <- struct{}{}: 654 default: 655 // never block 656 } 657 case PacketPong: 658 c.Logger.Debug("Receive Pong") 659 select { 660 case c.pongTimeoutCh <- false: 661 default: 662 // never block 663 } 664 case *PacketMsg: 665 channel, ok := c.channelsIdx[pkt.ChannelID] 666 if !ok || channel == nil { 667 err := fmt.Errorf("unknown channel %X", pkt.ChannelID) 668 c.Logger.Error("Connection failed @ recvRoutine", "conn", c, "err", err) 669 c.stopForError(err) 670 break FOR_LOOP 671 } 672 673 msgBytes, err := channel.recvPacketMsg(*pkt) 674 if err != nil { 675 if c.IsRunning() { 676 c.Logger.Error("Connection failed @ recvRoutine", "conn", c, "err", err) 677 c.stopForError(err) 678 } 679 break FOR_LOOP 680 } 681 if msgBytes != nil { 682 c.logReceiveMsg(pkt.ChannelID, msgBytes) 683 // NOTE: This means the reactor.Receive runs in the same thread as the p2p recv routine 684 c.onReceive(pkt.ChannelID, msgBytes) 685 } 686 default: 687 err := fmt.Errorf("unknown message type %v", reflect.TypeOf(packet)) 688 c.Logger.Error("Connection failed @ recvRoutine", "conn", c, "err", err) 689 c.stopForError(err) 690 break FOR_LOOP 691 } 692 } 693 694 // Cleanup 695 close(c.pong) 696 for range c.pong { 697 // Drain 698 } 699 } 700 701 func (c *MConnection) logReceiveMsg(channelID byte, msgBytes []byte) { 702 logParams := logDataPool.Get().(*logData) 703 logParams.Bytes = msgBytes 704 params := &logParams.Params 705 params[0] = "chID" 706 params[1] = channelID 707 params[2] = "msgBytes" 708 params[3] = &logParams.Bytes 709 c.Logger.Debug("Received bytes", logParams.Params[:4]...) 710 logDataPool.Put(logParams) 711 } 712 713 // not goroutine-safe 714 func (c *MConnection) stopPongTimer() { 715 if c.pongTimer != nil { 716 _ = c.pongTimer.Stop() 717 c.pongTimer = nil 718 } 719 } 720 721 // maxPacketMsgSize returns a maximum size of PacketMsg, including the overhead 722 // of amino encoding. 723 func (c *MConnection) maxPacketMsgSize() int { 724 return len(cdc.MustMarshalBinaryLengthPrefixed(PacketMsg{ 725 ChannelID: 0x01, 726 EOF: 1, 727 Bytes: make([]byte, c.config.MaxPacketMsgPayloadSize), 728 })) + 10 // leave room for changes in amino 729 } 730 731 type ConnectionStatus struct { 732 Duration time.Duration 733 SendMonitor flow.Status 734 RecvMonitor flow.Status 735 Channels []ChannelStatus 736 } 737 738 type ChannelStatus struct { 739 ID byte 740 SendQueueCapacity int 741 SendQueueSize int 742 Priority int 743 RecentlySent int64 744 } 745 746 func (c *MConnection) Status() ConnectionStatus { 747 var status ConnectionStatus 748 status.Duration = time.Since(c.created) 749 status.SendMonitor = c.sendMonitor.Status() 750 status.RecvMonitor = c.recvMonitor.Status() 751 status.Channels = make([]ChannelStatus, len(c.channels)) 752 for i, channel := range c.channels { 753 status.Channels[i] = ChannelStatus{ 754 ID: channel.desc.ID, 755 SendQueueCapacity: cap(channel.sendQueue), 756 SendQueueSize: int(atomic.LoadInt32(&channel.sendQueueSize)), 757 Priority: channel.desc.Priority, 758 RecentlySent: atomic.LoadInt64(&channel.recentlySent), 759 } 760 } 761 return status 762 } 763 764 //----------------------------------------------------------------------------- 765 766 type ChannelDescriptor struct { 767 ID byte 768 Priority int 769 SendQueueCapacity int 770 RecvBufferCapacity int 771 RecvMessageCapacity int 772 } 773 774 func (chDesc ChannelDescriptor) FillDefaults() (filled ChannelDescriptor) { 775 if chDesc.SendQueueCapacity == 0 { 776 chDesc.SendQueueCapacity = defaultSendQueueCapacity 777 } 778 if chDesc.RecvBufferCapacity == 0 { 779 chDesc.RecvBufferCapacity = defaultRecvBufferCapacity 780 } 781 if chDesc.RecvMessageCapacity == 0 { 782 chDesc.RecvMessageCapacity = defaultRecvMessageCapacity 783 } 784 filled = chDesc 785 return 786 } 787 788 // TODO: lowercase. 789 // NOTE: not goroutine-safe. 790 type Channel struct { 791 conn *MConnection 792 desc ChannelDescriptor 793 sendQueue chan []byte 794 sendQueueSize int32 // atomic. 795 recving []byte 796 sending []byte 797 recentlySent int64 // exponential moving average 798 799 maxPacketMsgPayloadSize int 800 801 Logger log.Logger 802 } 803 804 func newChannel(conn *MConnection, desc ChannelDescriptor) *Channel { 805 desc = desc.FillDefaults() 806 if desc.Priority <= 0 { 807 panic("Channel default priority must be a positive integer") 808 } 809 return &Channel{ 810 conn: conn, 811 desc: desc, 812 sendQueue: make(chan []byte, desc.SendQueueCapacity), 813 recving: make([]byte, 0, desc.RecvBufferCapacity), 814 maxPacketMsgPayloadSize: conn.config.MaxPacketMsgPayloadSize, 815 } 816 } 817 818 func (ch *Channel) SetLogger(l log.Logger) { 819 ch.Logger = l 820 } 821 822 var sendTimerPool = &sync.Pool{ 823 New: func() interface{} { 824 return time.NewTimer(defaultSendTimeout) 825 }, 826 } 827 828 // Queues message to send to this channel. 829 // Goroutine-safe 830 // Times out (and returns false) after defaultSendTimeout 831 func (ch *Channel) sendBytes(bytes []byte) bool { 832 sendTimer := sendTimerPool.Get().(*time.Timer) 833 if !sendTimer.Stop() { 834 select { 835 case <-sendTimer.C: 836 default: 837 } 838 } 839 sendTimer.Reset(defaultSendTimeout) 840 select { 841 case ch.sendQueue <- bytes: 842 sendTimerPool.Put(sendTimer) 843 atomic.AddInt32(&ch.sendQueueSize, 1) 844 return true 845 case <-sendTimer.C: 846 sendTimerPool.Put(sendTimer) 847 return false 848 } 849 } 850 851 // Queues message to send to this channel. 852 // Nonblocking, returns true if successful. 853 // Goroutine-safe 854 func (ch *Channel) trySendBytes(bytes []byte) bool { 855 select { 856 case ch.sendQueue <- bytes: 857 atomic.AddInt32(&ch.sendQueueSize, 1) 858 return true 859 default: 860 return false 861 } 862 } 863 864 // Goroutine-safe 865 func (ch *Channel) loadSendQueueSize() (size int) { 866 return int(atomic.LoadInt32(&ch.sendQueueSize)) 867 } 868 869 // Goroutine-safe 870 // Use only as a heuristic. 871 func (ch *Channel) canSend() bool { 872 return ch.loadSendQueueSize() < defaultSendQueueCapacity 873 } 874 875 // Returns true if any PacketMsgs are pending to be sent. 876 // Call before calling nextPacketMsg() 877 // Goroutine-safe 878 func (ch *Channel) isSendPending() bool { 879 if len(ch.sending) == 0 { 880 if len(ch.sendQueue) == 0 { 881 return false 882 } 883 ch.sending = <-ch.sendQueue 884 } 885 return true 886 } 887 888 // Creates a new PacketMsg to send. 889 // Not goroutine-safe 890 func (ch *Channel) nextPacketMsg() PacketMsg { 891 packet := PacketMsg{} 892 packet.ChannelID = ch.desc.ID 893 maxSize := ch.maxPacketMsgPayloadSize 894 packet.Bytes = ch.sending[:tmmath.MinInt(maxSize, len(ch.sending))] 895 if len(ch.sending) <= maxSize { 896 packet.EOF = byte(0x01) 897 ch.sending = nil 898 atomic.AddInt32(&ch.sendQueueSize, -1) // decrement sendQueueSize 899 } else { 900 packet.EOF = byte(0x00) 901 ch.sending = ch.sending[tmmath.MinInt(maxSize, len(ch.sending)):] 902 } 903 return packet 904 } 905 906 var packetBzSendPool = &sync.Pool{ 907 New: func() interface{} { 908 return &bytes.Buffer{} 909 }, 910 } 911 912 // Writes next PacketMsg to w and updates c.recentlySent. 913 // Not goroutine-safe 914 func (ch *Channel) writePacketMsgTo(w io.Writer) (n int64, err error) { 915 var packet = ch.nextPacketMsg() 916 917 packetMsgTypePrefix := getPacketMsgAminoTypePrefix() 918 bzSize := len(packetMsgTypePrefix) + packet.AminoSize(cdc) 919 bzSizeWithLenPrefix := amino.UvarintSize(uint64(bzSize)) + bzSize 920 921 // var buf = bytes.NewBuffer(make([]byte, 0, bzSizeWithLenPrefix)) 922 buf := packetBzSendPool.Get().(*bytes.Buffer) 923 defer packetBzSendPool.Put(buf) 924 buf.Reset() 925 buf.Grow(bzSizeWithLenPrefix) 926 927 err = amino.EncodeUvarintToBuffer(buf, uint64(bzSize)) 928 if err == nil { 929 buf.Write(packetMsgTypePrefix) 930 err = packet.MarshalAminoTo(cdc, buf) 931 if err == nil && buf.Len() == bzSizeWithLenPrefix { 932 bzNum := 0 933 bzNum, err = w.Write(buf.Bytes()) 934 n = int64(bzNum) 935 atomic.AddInt64(&ch.recentlySent, n) 936 return 937 } 938 } 939 940 n, err = cdc.MarshalBinaryLengthPrefixedWriterWithRegiteredMarshaller(w, packet) 941 if err != nil { 942 n, err = cdc.MarshalBinaryLengthPrefixedWriter(w, packet) 943 } 944 atomic.AddInt64(&ch.recentlySent, n) 945 return 946 } 947 948 func (ch *Channel) logRecvPacketMsg(packet PacketMsg) { 949 logParams := logDataPool.Get().(*logData) 950 logParams.Packet = packet 951 params := &logParams.Params 952 params[0] = "conn" 953 params[1] = ch.conn 954 params[2] = "packet" 955 params[3] = &logParams.Packet 956 ch.Logger.Debug("Read PacketMsg", logParams.Params[:4]...) 957 logDataPool.Put(logParams) 958 } 959 960 // Handles incoming PacketMsgs. It returns a message bytes if message is 961 // complete. NOTE message bytes may change on next call to recvPacketMsg. 962 // Not goroutine-safe 963 func (ch *Channel) recvPacketMsg(packet PacketMsg) ([]byte, error) { 964 ch.logRecvPacketMsg(packet) 965 966 var recvCap, recvReceived = ch.desc.RecvMessageCapacity, len(ch.recving) + len(packet.Bytes) 967 if recvCap < recvReceived { 968 return nil, fmt.Errorf("received message exceeds available capacity: %v < %v", recvCap, recvReceived) 969 } 970 ch.recving = append(ch.recving, packet.Bytes...) 971 if packet.EOF == byte(0x01) { 972 msgBytes := ch.recving 973 974 // clear the slice without re-allocating. 975 // http://stackoverflow.com/questions/16971741/how-do-you-clear-a-slice-in-go 976 // suggests this could be a memory leak, but we might as well keep the memory for the channel until it closes, 977 // at which point the recving slice stops being used and should be garbage collected 978 ch.recving = ch.recving[:0] // make([]byte, 0, ch.desc.RecvBufferCapacity) 979 return msgBytes, nil 980 } 981 return nil, nil 982 } 983 984 // Call this periodically to update stats for throttling purposes. 985 // Not goroutine-safe 986 func (ch *Channel) updateStats() { 987 // Exponential decay of stats. 988 // TODO: optimize. 989 atomic.StoreInt64(&ch.recentlySent, int64(float64(atomic.LoadInt64(&ch.recentlySent))*0.8)) 990 } 991 992 //---------------------------------------- 993 // Packet 994 995 type Packet interface { 996 AssertIsPacket() 997 } 998 999 const ( 1000 PacketPingName = "tendermint/p2p/PacketPing" 1001 PacketPongName = "tendermint/p2p/PacketPong" 1002 PacketMsgName = "tendermint/p2p/PacketMsg" 1003 ) 1004 1005 func RegisterPacket(cdc *amino.Codec) { 1006 cdc.RegisterInterface((*Packet)(nil), nil) 1007 cdc.RegisterConcrete(PacketPing{}, PacketPingName, nil) 1008 cdc.RegisterConcrete(PacketPong{}, PacketPongName, nil) 1009 cdc.RegisterConcrete(&PacketMsg{}, PacketMsgName, nil) 1010 1011 cdc.RegisterConcreteMarshaller(PacketPingName, func(_ *amino.Codec, i interface{}) ([]byte, error) { 1012 return []byte{}, nil 1013 }) 1014 cdc.RegisterConcreteMarshaller(PacketPongName, func(_ *amino.Codec, i interface{}) ([]byte, error) { 1015 return []byte{}, nil 1016 }) 1017 cdc.RegisterConcreteMarshaller(PacketMsgName, func(codec *amino.Codec, i interface{}) ([]byte, error) { 1018 if packet, ok := i.(PacketMsg); ok { 1019 return packet.MarshalToAmino(codec) 1020 } else if ppacket, ok := i.(*PacketMsg); ok { 1021 return ppacket.MarshalToAmino(codec) 1022 } else { 1023 return nil, fmt.Errorf("%v must be of type %v", i, PacketMsg{}) 1024 } 1025 }) 1026 cdc.RegisterConcreteUnmarshaller(PacketPingName, func(_ *amino.Codec, _ []byte) (interface{}, int, error) { 1027 return PacketPing{}, 0, nil 1028 }) 1029 cdc.RegisterConcreteUnmarshaller(PacketPongName, func(_ *amino.Codec, _ []byte) (interface{}, int, error) { 1030 return PacketPong{}, 0, nil 1031 }) 1032 cdc.RegisterConcreteUnmarshaller(PacketMsgName, func(codec *amino.Codec, data []byte) (interface{}, int, error) { 1033 var msg PacketMsg 1034 err := msg.UnmarshalFromAmino(codec, data) 1035 if err != nil { 1036 return nil, 0, err 1037 } else { 1038 return &msg, len(data), nil 1039 } 1040 }) 1041 1042 cdc.EnableBufferMarshaler(PacketMsg{}) 1043 } 1044 1045 func (PacketPing) AssertIsPacket() {} 1046 func (PacketPong) AssertIsPacket() {} 1047 func (PacketMsg) AssertIsPacket() {} 1048 1049 type PacketPing struct { 1050 } 1051 1052 func (p *PacketPing) UnmarshalFromAmino(_ *amino.Codec, _ []byte) error { 1053 return nil 1054 } 1055 1056 func (PacketPing) MarshalToAmino(_ *amino.Codec) ([]byte, error) { 1057 return []byte{}, nil 1058 } 1059 1060 type PacketPong struct { 1061 } 1062 1063 func (PacketPong) MarshalToAmino(_ *amino.Codec) ([]byte, error) { 1064 return []byte{}, nil 1065 } 1066 1067 func (p *PacketPong) UnmarshalFromAmino(_ *amino.Codec, _ []byte) error { 1068 return nil 1069 } 1070 1071 type PacketMsg struct { 1072 ChannelID byte 1073 EOF byte // 1 means message ends here. 1074 Bytes []byte 1075 } 1076 1077 func (mp PacketMsg) String() string { 1078 return fmt.Sprintf("PacketMsg{%X:%X T:%X}", mp.ChannelID, mp.Bytes, mp.EOF) 1079 } 1080 1081 func (mp *PacketMsg) Reset() { 1082 mp.ChannelID = 0 1083 mp.EOF = 0 1084 mp.Bytes = mp.Bytes[:0] 1085 } 1086 1087 func (mp PacketMsg) AminoSize(_ *amino.Codec) int { 1088 size := 0 1089 if mp.ChannelID != 0 { 1090 if mp.ChannelID <= 0b0111_1111 { 1091 size += 2 1092 } else { 1093 size += 3 1094 } 1095 } 1096 1097 if mp.EOF != 0 { 1098 if mp.EOF <= 0b0111_1111 { 1099 size += 2 1100 } else { 1101 size += 3 1102 } 1103 } 1104 1105 if len(mp.Bytes) != 0 { 1106 size += 1 + amino.ByteSliceSize(mp.Bytes) 1107 } 1108 1109 return size 1110 } 1111 1112 func (mp PacketMsg) MarshalToAmino(cdc *amino.Codec) ([]byte, error) { 1113 var buf bytes.Buffer 1114 buf.Grow(mp.AminoSize(cdc)) 1115 err := mp.MarshalAminoTo(cdc, &buf) 1116 if err != nil { 1117 return nil, err 1118 } 1119 return buf.Bytes(), nil 1120 } 1121 1122 func (mp PacketMsg) MarshalAminoTo(_ *amino.Codec, buf *bytes.Buffer) error { 1123 var err error 1124 // field 1 1125 if mp.ChannelID != 0 { 1126 const pbKey = 1 << 3 1127 buf.WriteByte(pbKey) 1128 if mp.ChannelID <= 0b0111_1111 { 1129 buf.WriteByte(mp.ChannelID) 1130 } else { 1131 buf.WriteByte(0b1000_0000 | (mp.ChannelID & 0x7F)) 1132 buf.WriteByte(mp.ChannelID >> 7) 1133 } 1134 } 1135 1136 // field 2 1137 if mp.EOF != 0 { 1138 const pbKey = 2 << 3 1139 buf.WriteByte(pbKey) 1140 if mp.EOF <= 0b0111_1111 { 1141 buf.WriteByte(mp.EOF) 1142 } else { 1143 buf.WriteByte(0b1000_0000 | (mp.EOF & 0x7F)) 1144 buf.WriteByte(mp.EOF >> 7) 1145 } 1146 } 1147 1148 // field 3 1149 if len(mp.Bytes) != 0 { 1150 const pbKey = 3<<3 | 2 1151 buf.WriteByte(pbKey) 1152 err = amino.EncodeUvarintToBuffer(buf, uint64(len(mp.Bytes))) 1153 if err != nil { 1154 return err 1155 } 1156 buf.Write(mp.Bytes) 1157 } 1158 1159 return nil 1160 } 1161 1162 func (mp *PacketMsg) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 1163 var dataLen uint64 = 0 1164 var subData []byte 1165 1166 for { 1167 data = data[dataLen:] 1168 1169 if len(data) == 0 { 1170 break 1171 } 1172 1173 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 1174 if err != nil { 1175 return err 1176 } 1177 data = data[1:] 1178 1179 if aminoType == amino.Typ3_ByteLength { 1180 var n int 1181 dataLen, n, err = amino.DecodeUvarint(data) 1182 if err != nil { 1183 return err 1184 } 1185 1186 data = data[n:] 1187 if len(data) < int(dataLen) { 1188 return errors.New("invalid data len") 1189 } 1190 subData = data[:dataLen] 1191 } 1192 1193 switch pos { 1194 case 1: 1195 vari, n, err := amino.DecodeUvarint(data) 1196 if err != nil { 1197 return err 1198 } 1199 mp.ChannelID = byte(vari) 1200 dataLen = uint64(n) 1201 case 2: 1202 vari, n, err := amino.DecodeUvarint(data) 1203 if err != nil { 1204 return err 1205 } 1206 mp.EOF = byte(vari) 1207 dataLen = uint64(n) 1208 case 3: 1209 if cap(mp.Bytes) >= len(subData) { 1210 mp.Bytes = mp.Bytes[:len(subData)] 1211 } else { 1212 mp.Bytes = make([]byte, len(subData)) 1213 } 1214 copy(mp.Bytes, subData) 1215 } 1216 } 1217 return nil 1218 } 1219 1220 var ( 1221 PacketPingTypePrefix = []byte{0x15, 0xC3, 0xD2, 0x89} 1222 PacketPongTypePrefix = []byte{0x8A, 0x79, 0x7F, 0xE2} 1223 PacketMsgTypePrefix = []byte{0xB0, 0x5B, 0x4F, 0x2C} 1224 1225 packetPing Packet = PacketPing{} 1226 packetPong Packet = PacketPong{} 1227 1228 packetBzPool = &sync.Pool{ 1229 New: func() interface{} { 1230 return new(bytes.Buffer) 1231 }, 1232 } 1233 packetLengthPrefixBzPool = &sync.Pool{ 1234 New: func() interface{} { 1235 return &[binary.MaxVarintLen64]byte{} 1236 }, 1237 } 1238 ) 1239 1240 func unmarshalPacketFromAminoReader(r io.Reader, maxSize int64, targetMsg *PacketMsg) (packet Packet, n int64, err error) { 1241 if maxSize < 0 { 1242 panic("maxSize cannot be negative.") 1243 } 1244 1245 // Read byte-length prefix. 1246 var l int64 1247 var buf = packetLengthPrefixBzPool.Get().(*[binary.MaxVarintLen64]byte) 1248 defer packetLengthPrefixBzPool.Put(buf) 1249 for i := 0; i < len(buf); i++ { 1250 _, err = r.Read(buf[i : i+1]) 1251 if err != nil { 1252 return 1253 } 1254 n += 1 1255 if buf[i]&0x80 == 0 { 1256 break 1257 } 1258 if n >= maxSize { 1259 err = fmt.Errorf("Read overflow, maxSize is %v but uvarint(length-prefix) is itself greater than maxSize.", maxSize) 1260 } 1261 } 1262 u64, _ := binary.Uvarint(buf[:]) 1263 if err != nil { 1264 return 1265 } 1266 if maxSize > 0 { 1267 if uint64(maxSize) < u64 { 1268 err = fmt.Errorf("Read overflow, maxSize is %v but this amino binary object is %v bytes.", maxSize, u64) 1269 return 1270 } 1271 if (maxSize - n) < int64(u64) { 1272 err = fmt.Errorf("Read overflow, maxSize is %v but this length-prefixed amino binary object is %v+%v bytes.", maxSize, n, u64) 1273 return 1274 } 1275 } 1276 l = int64(u64) 1277 if l < 0 { 1278 err = fmt.Errorf("Read overflow, this implementation can't read this because, why would anyone have this much data? Hello from 2018.") 1279 } 1280 1281 bbuf := packetBzPool.Get().(*bytes.Buffer) 1282 defer packetBzPool.Put(bbuf) 1283 bbuf.Grow(int(l)) 1284 var bz = bbuf.Bytes() 1285 if int64(cap(bz)) >= l { 1286 bz = bz[:l] 1287 } else { 1288 bz = make([]byte, l) 1289 } 1290 1291 // Read that many bytes. 1292 _, err = io.ReadFull(r, bz) 1293 if err != nil { 1294 return 1295 } 1296 n += l 1297 1298 if bytes.Equal(PacketPingTypePrefix, bz) { 1299 packet = packetPing 1300 return 1301 } else if bytes.Equal(PacketPongTypePrefix, bz) { 1302 packet = packetPong 1303 return 1304 } else if bytes.Equal(PacketMsgTypePrefix, bz[0:4]) { 1305 var msg *PacketMsg 1306 if targetMsg != nil { 1307 msg = targetMsg 1308 msg.Reset() 1309 } else { 1310 msg = &PacketMsg{} 1311 } 1312 err = msg.UnmarshalFromAmino(cdc, bz[4:]) 1313 if err == nil { 1314 packet = msg 1315 return 1316 } 1317 } 1318 var packet4amino Packet 1319 err = cdc.UnmarshalBinaryBare(bz, &packet4amino) 1320 packet = packet4amino 1321 return 1322 }