port.go 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package port
  2. import (
  3. "fmt"
  4. "net"
  5. "k8s.io/apimachinery/pkg/util/sets"
  6. )
  7. type Allocator struct {
  8. reserved sets.Int
  9. used sets.Int
  10. }
  11. // NewAllocator return a port allocator for testing.
  12. // Example: from: 10, to: 20, mod 4, index 1
  13. // Reserved ports: 13, 17
  14. func NewAllocator(from int, to int, mod int, index int) *Allocator {
  15. pa := &Allocator{
  16. reserved: sets.NewInt(),
  17. used: sets.NewInt(),
  18. }
  19. for i := from; i <= to; i++ {
  20. if i%mod == index {
  21. pa.reserved.Insert(i)
  22. }
  23. }
  24. return pa
  25. }
  26. func (pa *Allocator) Get() int {
  27. for i := 0; i < 10; i++ {
  28. port, _ := pa.reserved.PopAny()
  29. if port == 0 {
  30. return 0
  31. }
  32. // TODO: Distinguish between TCP and UDP
  33. l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
  34. if err != nil {
  35. // Maybe not controlled by us, mark it used.
  36. pa.used.Insert(port)
  37. continue
  38. }
  39. l.Close()
  40. pa.used.Insert(port)
  41. return port
  42. }
  43. return 0
  44. }
  45. func (pa *Allocator) Release(port int) {
  46. if pa.used.Has(port) {
  47. pa.used.Delete(port)
  48. pa.reserved.Insert(port)
  49. }
  50. }