blacklist.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package kcp
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. var (
  7. // BlacklistDuration sets a duration for which a session is blacklisted
  8. // once it's established. This is simillar to TIME_WAIT state in TCP, whereby
  9. // any connection attempt with the same session parameters is ignored for
  10. // some amount of time.
  11. //
  12. // This is only useful when dial attempts happen from a pre-determined port,
  13. // for example when you are dialing from the same connection you are listening on
  14. // to punch through NAT, and helps with the fact that KCP is state-less.
  15. // This helps better deal with scenarios where a process on one of the side (A)
  16. // get's restarted, and stray packets from other side (B) makes it look like
  17. // as if someone is trying to connect to A. Even if session dies on B,
  18. // new stray reply packets from A resurrect the session on B, causing the
  19. // session to be alive forever.
  20. BlacklistDuration time.Duration
  21. blacklist = blacklistMap{
  22. entries: make(map[sessionKey]time.Time),
  23. }
  24. )
  25. // a global map for blacklisting conversations
  26. type blacklistMap struct {
  27. entries map[sessionKey]time.Time
  28. reapAt time.Time
  29. mut sync.Mutex
  30. }
  31. func (m *blacklistMap) add(address string, conv uint32) {
  32. if BlacklistDuration == 0 {
  33. return
  34. }
  35. m.mut.Lock()
  36. timeout := time.Now().Add(BlacklistDuration)
  37. m.entries[sessionKey{
  38. addr: address,
  39. convID: conv,
  40. }] = timeout
  41. m.reap()
  42. m.mut.Unlock()
  43. }
  44. func (m *blacklistMap) has(address string, conv uint32) bool {
  45. if BlacklistDuration == 0 {
  46. return false
  47. }
  48. m.mut.Lock()
  49. t, ok := m.entries[sessionKey{
  50. addr: address,
  51. convID: conv,
  52. }]
  53. m.mut.Unlock()
  54. return ok && t.After(time.Now())
  55. }
  56. func (m *blacklistMap) reap() {
  57. now := time.Now()
  58. for k, t := range m.entries {
  59. if t.Before(now) {
  60. delete(m.entries, k)
  61. }
  62. }
  63. }