package probing import ( "sync" "time" ) var ( // weight factor α = 0.125 ) type Status interface { Total() int64 Loss() int64 Health() bool Err() error // Estimated smoothed round trip time SRTT() time.Duration // Estimated clock difference ClockDiff() time.Duration StopNotify() <-chan struct{} } type status struct { mu sync.Mutex srtt time.Duration total int64 loss int64 health bool err error clockdiff time.Duration stopC chan struct{} } // SRTT = (1-α) * SRTT + α * RTT func (s *status) SRTT() time.Duration { s.mu.Lock() defer s.mu.Unlock() return s.srtt } func (s *status) Total() int64 { s.mu.Lock() defer s.mu.Unlock() return s.total } func (s *status) Loss() int64 { s.mu.Lock() defer s.mu.Unlock() return s.loss } func (s *status) Health() bool { s.mu.Lock() defer s.mu.Unlock() return s.health } func (s *status) Err() error { s.mu.Lock() defer s.mu.Unlock() return s.err } func (s *status) ClockDiff() time.Duration { s.mu.Lock() defer s.mu.Unlock() return s.clockdiff } func (s *status) StopNotify() <-chan struct{} { return s.stopC } func (s *status) record(rtt time.Duration, when time.Time) { s.mu.Lock() defer s.mu.Unlock() s.total += 1 s.health = true s.srtt = time.Duration((1-α)*float64(s.srtt) + α*float64(rtt)) s.clockdiff = time.Now().Sub(when) - s.srtt/2 s.err = nil } func (s *status) recordFailure(err error) { s.mu.Lock() defer s.mu.Unlock() s.total++ s.health = false s.loss += 1 s.err = err } func (s *status) reset() { s.mu.Lock() defer s.mu.Unlock() s.srtt = 0 s.total = 0 s.loss = 0 s.health = false s.clockdiff = 0 s.err = nil }