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