...
1
16
17 package net
18
19 import (
20 "fmt"
21 "strconv"
22 "strings"
23 )
24
25
26
27 type PortRange struct {
28 Base int
29 Size int
30 }
31
32
33 func (pr *PortRange) Contains(p int) bool {
34 return (p >= pr.Base) && ((p - pr.Base) < pr.Size)
35 }
36
37
38
39 func (pr PortRange) String() string {
40 if pr.Size == 0 {
41 return ""
42 }
43 return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1)
44 }
45
46
47
48
49 func (pr *PortRange) Set(value string) error {
50 const (
51 SinglePortNotation = 1 << iota
52 HyphenNotation
53 PlusNotation
54 )
55
56 value = strings.TrimSpace(value)
57 hyphenIndex := strings.Index(value, "-")
58 plusIndex := strings.Index(value, "+")
59
60 if value == "" {
61 pr.Base = 0
62 pr.Size = 0
63 return nil
64 }
65
66 var err error
67 var low, high int
68 var notation int
69
70 if plusIndex == -1 && hyphenIndex == -1 {
71 notation |= SinglePortNotation
72 }
73 if hyphenIndex != -1 {
74 notation |= HyphenNotation
75 }
76 if plusIndex != -1 {
77 notation |= PlusNotation
78 }
79
80 switch notation {
81 case SinglePortNotation:
82 var port int
83 port, err = strconv.Atoi(value)
84 if err != nil {
85 return err
86 }
87 low = port
88 high = port
89 case HyphenNotation:
90 low, err = strconv.Atoi(value[:hyphenIndex])
91 if err != nil {
92 return err
93 }
94 high, err = strconv.Atoi(value[hyphenIndex+1:])
95 if err != nil {
96 return err
97 }
98 case PlusNotation:
99 var offset int
100 low, err = strconv.Atoi(value[:plusIndex])
101 if err != nil {
102 return err
103 }
104 offset, err = strconv.Atoi(value[plusIndex+1:])
105 if err != nil {
106 return err
107 }
108 high = low + offset
109 default:
110 return fmt.Errorf("unable to parse port range: %s", value)
111 }
112
113 if low > 65535 || high > 65535 {
114 return fmt.Errorf("the port range cannot be greater than 65535: %s", value)
115 }
116
117 if high < low {
118 return fmt.Errorf("end port cannot be less than start port: %s", value)
119 }
120
121 pr.Base = low
122 pr.Size = 1 + high - low
123 return nil
124 }
125
126
127
128 func (*PortRange) Type() string {
129 return "portRange"
130 }
131
132
133
134 func ParsePortRange(value string) (*PortRange, error) {
135 pr := &PortRange{}
136 err := pr.Set(value)
137 if err != nil {
138 return nil, err
139 }
140 return pr, nil
141 }
142
143 func ParsePortRangeOrDie(value string) *PortRange {
144 pr, err := ParsePortRange(value)
145 if err != nil {
146 panic(fmt.Sprintf("couldn't parse port range %q: %v", value, err))
147 }
148 return pr
149 }
150
View as plain text