port_range.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package net
  14. import (
  15. "fmt"
  16. "strconv"
  17. "strings"
  18. )
  19. // PortRange represents a range of TCP/UDP ports. To represent a single port,
  20. // set Size to 1.
  21. type PortRange struct {
  22. Base int
  23. Size int
  24. }
  25. // Contains tests whether a given port falls within the PortRange.
  26. func (pr *PortRange) Contains(p int) bool {
  27. return (p >= pr.Base) && ((p - pr.Base) < pr.Size)
  28. }
  29. // String converts the PortRange to a string representation, which can be
  30. // parsed by PortRange.Set or ParsePortRange.
  31. func (pr PortRange) String() string {
  32. if pr.Size == 0 {
  33. return ""
  34. }
  35. return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1)
  36. }
  37. // Set parses a string of the form "value", "min-max", or "min+offset", inclusive at both ends, and
  38. // sets the PortRange from it. This is part of the flag.Value and pflag.Value
  39. // interfaces.
  40. func (pr *PortRange) Set(value string) error {
  41. const (
  42. SinglePortNotation = 1 << iota
  43. HyphenNotation
  44. PlusNotation
  45. )
  46. value = strings.TrimSpace(value)
  47. hyphenIndex := strings.Index(value, "-")
  48. plusIndex := strings.Index(value, "+")
  49. if value == "" {
  50. pr.Base = 0
  51. pr.Size = 0
  52. return nil
  53. }
  54. var err error
  55. var low, high int
  56. var notation int
  57. if plusIndex == -1 && hyphenIndex == -1 {
  58. notation |= SinglePortNotation
  59. }
  60. if hyphenIndex != -1 {
  61. notation |= HyphenNotation
  62. }
  63. if plusIndex != -1 {
  64. notation |= PlusNotation
  65. }
  66. switch notation {
  67. case SinglePortNotation:
  68. var port int
  69. port, err = strconv.Atoi(value)
  70. if err != nil {
  71. return err
  72. }
  73. low = port
  74. high = port
  75. case HyphenNotation:
  76. low, err = strconv.Atoi(value[:hyphenIndex])
  77. if err != nil {
  78. return err
  79. }
  80. high, err = strconv.Atoi(value[hyphenIndex+1:])
  81. if err != nil {
  82. return err
  83. }
  84. case PlusNotation:
  85. var offset int
  86. low, err = strconv.Atoi(value[:plusIndex])
  87. if err != nil {
  88. return err
  89. }
  90. offset, err = strconv.Atoi(value[plusIndex+1:])
  91. if err != nil {
  92. return err
  93. }
  94. high = low + offset
  95. default:
  96. return fmt.Errorf("unable to parse port range: %s", value)
  97. }
  98. if low > 65535 || high > 65535 {
  99. return fmt.Errorf("the port range cannot be greater than 65535: %s", value)
  100. }
  101. if high < low {
  102. return fmt.Errorf("end port cannot be less than start port: %s", value)
  103. }
  104. pr.Base = low
  105. pr.Size = 1 + high - low
  106. return nil
  107. }
  108. // Type returns a descriptive string about this type. This is part of the
  109. // pflag.Value interface.
  110. func (*PortRange) Type() string {
  111. return "portRange"
  112. }
  113. // ParsePortRange parses a string of the form "min-max", inclusive at both
  114. // ends, and initializs a new PortRange from it.
  115. func ParsePortRange(value string) (*PortRange, error) {
  116. pr := &PortRange{}
  117. err := pr.Set(value)
  118. if err != nil {
  119. return nil, err
  120. }
  121. return pr, nil
  122. }
  123. func ParsePortRangeOrDie(value string) *PortRange {
  124. pr, err := ParsePortRange(value)
  125. if err != nil {
  126. panic(fmt.Sprintf("couldn't parse port range %q: %v", value, err))
  127. }
  128. return pr
  129. }