port.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package addrgen
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strconv"
  6. "strings"
  7. "github.com/SenseUnit/dtlspipe/randpool"
  8. )
  9. var _ PortGen = PortRange{}
  10. type PortRange struct {
  11. portBase uint16
  12. portNum uint16
  13. }
  14. func NewPortRange(start, end uint16) PortRange {
  15. if end < start {
  16. return NewPortRange(end, start)
  17. }
  18. return PortRange{
  19. portBase: start,
  20. portNum: end - start + 1,
  21. }
  22. }
  23. func (p PortRange) Port() uint16 {
  24. var delta uint16
  25. randpool.Borrow(func(r *rand.Rand) {
  26. delta = uint16(r.Intn(int(p.portNum)))
  27. })
  28. return p.portBase + delta
  29. }
  30. func (p PortRange) Power() uint16 {
  31. return p.portNum
  32. }
  33. var _ PortGen = SinglePort(0)
  34. type SinglePort uint16
  35. func (p SinglePort) Port() uint16 {
  36. return uint16(p)
  37. }
  38. func (p SinglePort) Power() uint16 {
  39. return 1
  40. }
  41. func ParsePortRangeSpec(spec string) (PortGen, error) {
  42. parts := strings.SplitN(spec, "-", 2)
  43. switch len(parts) {
  44. case 1:
  45. port, err := strconv.ParseUint(parts[0], 10, 16)
  46. if err != nil {
  47. return nil, fmt.Errorf("unable to parse port specification %q: %w", parts[0], err)
  48. }
  49. return SinglePort(port), nil
  50. case 2:
  51. start, err := strconv.ParseUint(parts[0], 10, 16)
  52. if err != nil {
  53. return nil, fmt.Errorf("unable to parse port specification %q: %w", parts[0], err)
  54. }
  55. end, err := strconv.ParseUint(parts[1], 10, 16)
  56. if err != nil {
  57. return nil, fmt.Errorf("unable to parse port specification %q: %w", parts[1], err)
  58. }
  59. return NewPortRange(uint16(start), uint16(end)), nil
  60. }
  61. return nil, fmt.Errorf("unexpected number of components: %d", len(parts))
  62. }