123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- package ws
- import (
- "errors"
- "github.com/gorilla/websocket"
- "sync"
- "time"
- )
- const (
- maxMessageSize = 1024 * 1024 * 10
- basePingInterval = 5 * time.Second
- maxPingInterval = 120 * time.Second
- minPingInterval = 15 * time.Second
- )
- type LatencyMeasurer struct {
- measurements []time.Duration
- lastLatency time.Duration
- mu sync.Mutex
- lastPingTime time.Time
- maxMeasurements int
- }
- func NewLatencyMeasurer(windowSize int) *LatencyMeasurer {
- return &LatencyMeasurer{
- maxMeasurements: windowSize,
- measurements: make([]time.Duration, 0, windowSize),
- lastLatency: basePingInterval,
- }
- }
- func (lm *LatencyMeasurer) SendPing(conn *websocket.Conn) error {
- lm.mu.Lock()
- defer lm.mu.Unlock()
- if conn == nil {
- return errors.New("connection closed")
- }
-
- err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWaitTimeout))
- if err != nil {
- return err
- }
- lm.lastPingTime = time.Now()
- return nil
- }
- func (lm *LatencyMeasurer) CalculateLatency() {
- lm.mu.Lock()
- defer lm.mu.Unlock()
- if lm.lastPingTime.IsZero() {
- return
- }
-
- rtt := time.Since(lm.lastPingTime)
-
- if len(lm.measurements) >= lm.maxMeasurements {
- lm.measurements = lm.measurements[1:]
- }
- lm.measurements = append(lm.measurements, rtt)
-
- sum := time.Duration(0)
- for _, d := range lm.measurements {
- sum += d
- }
- lm.lastLatency = sum / time.Duration(len(lm.measurements))
- if lm.lastLatency > maxPingInterval {
- lm.lastLatency = maxPingInterval
- }
- if lm.lastLatency < minPingInterval {
- lm.lastLatency = minPingInterval
- }
- }
- func (lm *LatencyMeasurer) GetLatency() time.Duration {
- lm.mu.Lock()
- defer lm.mu.Unlock()
- return lm.lastLatency
- }
- func SetupLatencyMeasurement(conn *websocket.Conn) *LatencyMeasurer {
- lm := NewLatencyMeasurer(5)
- conn.SetPongHandler(func(appData string) error {
- lm.CalculateLatency()
- return nil
- })
- return lm
- }
|