orchard/internal/command/portforward/portspec.go

64 lines
1.2 KiB
Go

package portforward
import (
"errors"
"fmt"
"strconv"
"strings"
)
var ErrInvalidPortSpec = errors.New("invalid port-forwarding specification")
type PortSpec struct {
LocalPort uint16
RemotePort uint16
}
func NewPortSpec(portSpecRaw string) (*PortSpec, error) {
splits := strings.Split(portSpecRaw, ":")
switch len(splits) {
case 1:
remotePort, err := parsePort(splits[0])
if err != nil {
return nil, err
}
return &PortSpec{
LocalPort: 0,
RemotePort: remotePort,
}, nil
case 2:
localPort, err := parsePort(splits[0])
if err != nil {
return nil, err
}
remotePort, err := parsePort(splits[1])
if err != nil {
return nil, err
}
return &PortSpec{
LocalPort: localPort,
RemotePort: remotePort,
}, nil
default:
return nil, fmt.Errorf("%w: expected 1 or 2 components delimited by \":\", found %d",
ErrInvalidPortSpec, len(splits))
}
}
func parsePort(s string) (uint16, error) {
port, err := strconv.ParseUint(s, 10, 16)
if err != nil {
return 0, err
}
if port < 1 || port > 65535 {
return 0, fmt.Errorf("%w: only ports in range [1, 65535] are allowed", ErrInvalidPortSpec)
}
return uint16(port), nil
}