summaryrefslogtreecommitdiff
path: root/network/latencyTracker.go
diff options
context:
space:
mode:
Diffstat (limited to 'network/latencyTracker.go')
-rw-r--r--network/latencyTracker.go170
1 files changed, 0 insertions, 170 deletions
diff --git a/network/latencyTracker.go b/network/latencyTracker.go
deleted file mode 100644
index ff503ddb2..000000000
--- a/network/latencyTracker.go
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (C) 2019-2021 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
-
-package network
-
-import (
- "errors"
- "net"
- "strconv"
- "sync/atomic"
- "time"
-
- "github.com/algorand/websocket"
-
- "github.com/algorand/go-deadlock"
-
- "github.com/algorand/go-algorand/config"
-)
-
-const pongMessageWriteDuration = time.Second
-const pingMessageWriteDuration = time.Second
-
-var errInvalidPongMessageContent = errors.New("invalid pong message content")
-var errInvalidPingMessageContent = errors.New("invalid ping message content")
-
-// latencyTracker works in conjunction with the wspeer in measuring the
-// communication latency over the websocket connection.
-type latencyTracker struct {
- // receivedPacketCounter is a counter for all incoming messages
- // placed here to be aligned with 64bit address.
- receivedPacketCounter uint64
-
- // latency is the effective latency of the connection.
- // placed here to be aligned with 64bit address.
- latency int64
-
- // lastPingSentTime is the timestamp at which we last sent a message.
- // this variable is only touched by checkPingSending, and therefore doesn't
- // need to be syncronized. The "clone" of this variable lastPingSentTimeSynced,
- // is being used by both the checkPingSending as well as by the pongHandler
- // and therefore require synchronization.
- lastPingSentTime int64
-
- // static variables
- // ( doesn't get changed after init, hence, no synchronization needed )
-
- // conn is the underlying connection object.
- conn wsPeerWebsocketConn
-
- // enabled indicates whether the pingpong is currently enabled or not.
- enabled bool
-
- // pingInterval is the max interval at which the client would send ping messages.
- pingInterval time.Duration
-
- // lastPingMu synchronize the protected variables that might be modified across
- // the checkPingSending and the pongHandler. All the variable below this point
- // need to be syncronized with the mutex.
- lastPingMu deadlock.Mutex
-
- // lastPingID is the last ping ID, a monotonic growing number used to ensure
- // that the pong message we've receive corresponds to the latest ping message
- // that we've sent.
- lastPingID uint64
-
- // lastPingReceivedCounter stores message counter at the time we sent the ping.
- // In order to ensure the timing accuracy, we want to have no other messages
- // being exchanged. This, of course, would only delay the ping-pong until a
- // better measurement could be taken.
- lastPingReceivedCounter uint64
-
- // lastPingSentTimeSynced, as stated above, is the syncronized version of lastPingSentTime.
- // it is used only in the case where we end up sending the ping message.
- lastPingSentTimeSynced int64
-}
-
-func (lt *latencyTracker) init(conn wsPeerWebsocketConn, cfg config.Local, initialConnectionLatency time.Duration) {
- lt.conn = conn
- lt.enabled = cfg.PeerPingPeriodSeconds > 0 && cfg.EnablePingHandler
- lt.latency = int64(initialConnectionLatency)
- lt.pingInterval = time.Duration(cfg.PeerPingPeriodSeconds) * time.Second
- conn.SetPingHandler(lt.pingHandler)
- conn.SetPongHandler(lt.pongHandler)
-}
-
-func (lt *latencyTracker) pingHandler(message string) error {
- if _, err := strconv.Atoi(message); err != nil {
- return errInvalidPingMessageContent
- }
- err := lt.conn.WriteControl(websocket.PongMessage, []byte(message), time.Now().Add(pongMessageWriteDuration))
- if err == websocket.ErrCloseSent {
- return nil
- } else if e, ok := err.(net.Error); ok && e.Temporary() {
- return nil
- }
- return err
-}
-
-func (lt *latencyTracker) pongHandler(message string) error {
- pongID, err := strconv.Atoi(message)
- if err != nil {
- return errInvalidPongMessageContent
- }
-
- lt.lastPingMu.Lock()
- defer lt.lastPingMu.Unlock()
-
- if uint64(pongID) != lt.lastPingID {
- // we've sent more than one ping since; ignore this message.
- return nil
- }
- if lt.receivedPacketCounter != lt.lastPingReceivedCounter {
- // we've received other messages since the one that we sent. The timing
- // here would not be accurate.
- return nil
- }
- lastPingSentTime := time.Unix(0, lt.lastPingSentTimeSynced)
- roundtripDuration := time.Since(lastPingSentTime)
- atomic.StoreInt64(&lt.latency, roundtripDuration.Nanoseconds())
- return nil
-}
-
-func (lt *latencyTracker) getConnectionLatency() time.Duration {
- return time.Duration(atomic.LoadInt64(&lt.latency))
-}
-
-func (lt *latencyTracker) checkPingSending(now *time.Time) error {
- if !lt.enabled {
- return nil
- }
- if now.Sub(time.Unix(0, lt.lastPingSentTime)) < lt.pingInterval {
- return nil
- }
-
- // it looks like it's time to send a ping :
- lt.lastPingMu.Lock()
- defer lt.lastPingMu.Unlock()
-
- lt.lastPingID++
- err := lt.conn.WriteControl(websocket.PingMessage, []byte(strconv.Itoa(int(lt.lastPingID))), now.Add(pingMessageWriteDuration))
- if err == websocket.ErrCloseSent {
- return nil
- } else if e, ok := err.(net.Error); ok && e.Temporary() {
- return nil
- }
- if err != nil {
- return err
- }
- lt.lastPingSentTimeSynced = now.UnixNano()
- lt.lastPingReceivedCounter = atomic.LoadUint64(&lt.receivedPacketCounter)
- lt.lastPingSentTime = lt.lastPingSentTimeSynced
- return nil
-}
-
-func (lt *latencyTracker) increaseReceivedCounter() {
- atomic.AddUint64(&lt.receivedPacketCounter, 1)
-}