github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/portspec/portspec.go (about)

     1  package portspec
     2  
     3  // This package manages all port spec functions and validations and can
     4  // be reused by all other packages.
     5  
     6  import (
     7  	"errors"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  // PortSpec is the specification of a port or port range
    13  type PortSpec struct {
    14  	Min   uint16 `json:"Min,omitempty"`
    15  	Max   uint16 `json:"Max,omitempty"`
    16  	value interface{}
    17  }
    18  
    19  // NewPortSpec creates a new port spec
    20  func NewPortSpec(min, max uint16, value interface{}) (*PortSpec, error) {
    21  
    22  	if min > max {
    23  		return nil, errors.New("Min port greater than max")
    24  	}
    25  
    26  	return &PortSpec{
    27  		Min:   min,
    28  		Max:   max,
    29  		value: value,
    30  	}, nil
    31  }
    32  
    33  // NewPortSpecFromString creates a new port spec
    34  func NewPortSpecFromString(ports string, value interface{}) (*PortSpec, error) {
    35  
    36  	var min, max int
    37  	var err error
    38  	if strings.Contains(ports, ":") {
    39  		portMinMax := strings.SplitN(ports, ":", 2)
    40  		if len(portMinMax) != 2 {
    41  			return nil, errors.New("Invalid port specification")
    42  		}
    43  
    44  		min, err = strconv.Atoi(portMinMax[0])
    45  		if err != nil || min < 0 {
    46  			return nil, errors.New("Min is not a valid port")
    47  		}
    48  
    49  		max, err = strconv.Atoi(portMinMax[1])
    50  		if err != nil || max >= 65536 {
    51  			return nil, errors.New("Max is not a valid port")
    52  		}
    53  	} else {
    54  		min, err = strconv.Atoi(ports)
    55  		if err != nil || min >= 65536 || min < 0 {
    56  			return nil, errors.New("Port is larger than 2^16 or invalid port")
    57  		}
    58  		max = min
    59  	}
    60  
    61  	return NewPortSpec(uint16(min), uint16(max), value)
    62  }
    63  
    64  // IsMultiPort returns true if the spec is for multiple ports.
    65  func (s *PortSpec) IsMultiPort() bool {
    66  	return s.Min != s.Max
    67  }
    68  
    69  // SinglePort returns the port of a non multi-port spec
    70  func (s *PortSpec) SinglePort() (uint16, error) {
    71  	if s.IsMultiPort() {
    72  		return 0, errors.New("Not a single port specification")
    73  	}
    74  
    75  	return s.Min, nil
    76  }
    77  
    78  // Range returns the range of a spec.
    79  func (s *PortSpec) Range() (uint16, uint16) {
    80  	return s.Min, s.Max
    81  }
    82  
    83  // MultiPort returns the multi-port range as a string.
    84  func (s *PortSpec) String() string {
    85  	if s.IsMultiPort() {
    86  		return strconv.Itoa(int(s.Min)) + ":" + strconv.Itoa(int(s.Max))
    87  	}
    88  
    89  	return strconv.Itoa(int(s.Min))
    90  }
    91  
    92  // Value returns the value of the portspec if one is there
    93  func (s *PortSpec) Value() interface{} {
    94  	return s.value
    95  }
    96  
    97  // Overlaps returns true if the provided port spec overlaps with the given one.
    98  func (s *PortSpec) Overlaps(p *PortSpec) bool {
    99  	a := p
   100  	b := s
   101  	if a.Min > b.Min {
   102  		a = s
   103  		b = p
   104  	}
   105  	if a.Max >= b.Min {
   106  		return true
   107  	}
   108  	return false
   109  }
   110  
   111  // Intersects returns true if the provided port spec intersect with the given one.
   112  func (s *PortSpec) Intersects(p *PortSpec) bool {
   113  	if p.Min == p.Max {
   114  		return s.IsIncluded(int(p.Min))
   115  	}
   116  	return s.IsIncluded(int(p.Min)) && s.IsIncluded(int(p.Max))
   117  }
   118  
   119  // IsIncluded returns trues if a port is within the range of the portspec
   120  func (s *PortSpec) IsIncluded(port int) bool {
   121  	p := uint16(port)
   122  	if s.Min <= p && p <= s.Max {
   123  		return true
   124  	}
   125  	return false
   126  }