conn_map.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package vnet
  2. import (
  3. "errors"
  4. "net"
  5. "sync"
  6. )
  7. var (
  8. errAddressAlreadyInUse = errors.New("address already in use")
  9. errNoSuchUDPConn = errors.New("no such UDPConn")
  10. errCannotRemoveUnspecifiedIP = errors.New("cannot remove unspecified IP by the specified IP")
  11. )
  12. type udpConnMap struct {
  13. portMap map[int][]*UDPConn
  14. mutex sync.RWMutex
  15. }
  16. func newUDPConnMap() *udpConnMap {
  17. return &udpConnMap{
  18. portMap: map[int][]*UDPConn{},
  19. }
  20. }
  21. func (m *udpConnMap) insert(conn *UDPConn) error {
  22. m.mutex.Lock()
  23. defer m.mutex.Unlock()
  24. udpAddr := conn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
  25. // check if the port has a listener
  26. conns, ok := m.portMap[udpAddr.Port]
  27. if ok {
  28. if udpAddr.IP.IsUnspecified() {
  29. return errAddressAlreadyInUse
  30. }
  31. for _, conn := range conns {
  32. laddr := conn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
  33. if laddr.IP.IsUnspecified() || laddr.IP.Equal(udpAddr.IP) {
  34. return errAddressAlreadyInUse
  35. }
  36. }
  37. conns = append(conns, conn)
  38. } else {
  39. conns = []*UDPConn{conn}
  40. }
  41. m.portMap[udpAddr.Port] = conns
  42. return nil
  43. }
  44. func (m *udpConnMap) find(addr net.Addr) (*UDPConn, bool) {
  45. m.mutex.Lock() // could be RLock, but we have delete() op
  46. defer m.mutex.Unlock()
  47. udpAddr := addr.(*net.UDPAddr) //nolint:forcetypeassert
  48. if conns, ok := m.portMap[udpAddr.Port]; ok {
  49. if udpAddr.IP.IsUnspecified() {
  50. // pick the first one appears in the iteration
  51. if len(conns) == 0 {
  52. // This can't happen!
  53. delete(m.portMap, udpAddr.Port)
  54. return nil, false
  55. }
  56. return conns[0], true
  57. }
  58. for _, conn := range conns {
  59. laddr := conn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
  60. if laddr.IP.IsUnspecified() || laddr.IP.Equal(udpAddr.IP) {
  61. return conn, ok
  62. }
  63. }
  64. }
  65. return nil, false
  66. }
  67. func (m *udpConnMap) delete(addr net.Addr) error {
  68. m.mutex.Lock()
  69. defer m.mutex.Unlock()
  70. udpAddr := addr.(*net.UDPAddr) //nolint:forcetypeassert
  71. conns, ok := m.portMap[udpAddr.Port]
  72. if !ok {
  73. return errNoSuchUDPConn
  74. }
  75. if udpAddr.IP.IsUnspecified() {
  76. // remove all from this port
  77. delete(m.portMap, udpAddr.Port)
  78. return nil
  79. }
  80. newConns := []*UDPConn{}
  81. for _, conn := range conns {
  82. laddr := conn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
  83. if laddr.IP.IsUnspecified() {
  84. // This can't happen!
  85. return errCannotRemoveUnspecifiedIP
  86. }
  87. if laddr.IP.Equal(udpAddr.IP) {
  88. continue
  89. }
  90. newConns = append(newConns, conn)
  91. }
  92. if len(newConns) == 0 {
  93. delete(m.portMap, udpAddr.Port)
  94. } else {
  95. m.portMap[udpAddr.Port] = newConns
  96. }
  97. return nil
  98. }
  99. // size returns the number of UDPConns (UDP listeners)
  100. func (m *udpConnMap) size() int {
  101. m.mutex.RLock()
  102. defer m.mutex.RUnlock()
  103. n := 0
  104. for _, conns := range m.portMap {
  105. n += len(conns)
  106. }
  107. return n
  108. }