Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package connection_limits
  4. import (
  5. "time"
  6. )
  7. // ThrottleDetails holds the connection-throttling details for a subnet/IP.
  8. type ThrottleDetails struct {
  9. Start time.Time
  10. Count int
  11. }
  12. // GenericThrottle allows enforcing limits of the form
  13. // "at most X events per time window of duration Y"
  14. type GenericThrottle struct {
  15. ThrottleDetails // variable state: what events have been seen
  16. // these are constant after creation:
  17. Duration time.Duration // window length to consider
  18. Limit int // number of events allowed per window
  19. }
  20. // Touch checks whether an additional event is allowed:
  21. // it either denies it (by returning false) or allows it (by returning true)
  22. // and records it
  23. func (g *GenericThrottle) Touch() (throttled bool, remainingTime time.Duration) {
  24. return g.touch(time.Now().UTC())
  25. }
  26. func (g *GenericThrottle) touch(now time.Time) (throttled bool, remainingTime time.Duration) {
  27. if g.Limit == 0 {
  28. return // limit of 0 disables throttling
  29. }
  30. elapsed := now.Sub(g.Start)
  31. if elapsed > g.Duration {
  32. // reset window, record the operation
  33. g.Start = now
  34. g.Count = 1
  35. return false, 0
  36. } else if g.Count >= g.Limit {
  37. // we are throttled
  38. return true, g.Start.Add(g.Duration).Sub(now)
  39. } else {
  40. // we are not throttled, record the operation
  41. g.Count += 1
  42. return false, 0
  43. }
  44. }