package addrgen import ( "fmt" "math/rand" "strconv" "strings" "github.com/SenseUnit/dtlspipe/randpool" ) var _ PortGen = PortRange{} type PortRange struct { portBase uint16 portNum uint16 } func NewPortRange(start, end uint16) PortRange { if end < start { return NewPortRange(end, start) } return PortRange{ portBase: start, portNum: end - start + 1, } } func (p PortRange) Port() uint16 { var delta uint16 randpool.Borrow(func(r *rand.Rand) { delta = uint16(r.Intn(int(p.portNum))) }) return p.portBase + delta } func (p PortRange) Power() uint16 { return p.portNum } var _ PortGen = SinglePort(0) type SinglePort uint16 func (p SinglePort) Port() uint16 { return uint16(p) } func (p SinglePort) Power() uint16 { return 1 } func ParsePortRangeSpec(spec string) (PortGen, error) { parts := strings.SplitN(spec, "-", 2) switch len(parts) { case 1: port, err := strconv.ParseUint(parts[0], 10, 16) if err != nil { return nil, fmt.Errorf("unable to parse port specification %q: %w", parts[0], err) } return SinglePort(port), nil case 2: start, err := strconv.ParseUint(parts[0], 10, 16) if err != nil { return nil, fmt.Errorf("unable to parse port specification %q: %w", parts[0], err) } end, err := strconv.ParseUint(parts[1], 10, 16) if err != nil { return nil, fmt.Errorf("unable to parse port specification %q: %w", parts[1], err) } return NewPortRange(uint16(start), uint16(end)), nil } return nil, fmt.Errorf("unexpected number of components: %d", len(parts)) }