hysteria/extras/transport/udphop/addr.go
2023-08-30 20:02:18 -07:00

86 lines
1.8 KiB
Go

package udphop
import (
"errors"
"net"
"strconv"
"strings"
)
var ErrInvalidPort = errors.New("invalid port")
// UDPHopAddr contains an IP address and a list of ports.
type UDPHopAddr struct {
IP net.IP
Ports []uint16
PortStr string
}
func (a *UDPHopAddr) Network() string {
return "udphop"
}
func (a *UDPHopAddr) String() string {
return net.JoinHostPort(a.IP.String(), a.PortStr)
}
// addrs returns a list of net.Addr's, one for each port.
func (a *UDPHopAddr) addrs() ([]net.Addr, error) {
var addrs []net.Addr
for _, port := range a.Ports {
addr := &net.UDPAddr{
IP: a.IP,
Port: int(port),
}
addrs = append(addrs, addr)
}
return addrs, nil
}
func ResolveUDPHopAddr(addr string) (*UDPHopAddr, error) {
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
ip, err := net.ResolveIPAddr("ip", host)
if err != nil {
return nil, err
}
result := &UDPHopAddr{
IP: ip.IP,
PortStr: portStr,
}
portStrs := strings.Split(portStr, ",")
for _, portStr := range portStrs {
if strings.Contains(portStr, "-") {
// Port range
portRange := strings.Split(portStr, "-")
if len(portRange) != 2 {
return nil, ErrInvalidPort
}
start, err := strconv.ParseUint(portRange[0], 10, 16)
if err != nil {
return nil, ErrInvalidPort
}
end, err := strconv.ParseUint(portRange[1], 10, 16)
if err != nil {
return nil, ErrInvalidPort
}
if start > end {
start, end = end, start
}
for i := start; i <= end; i++ {
result.Ports = append(result.Ports, uint16(i))
}
} else {
// Single port
port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
return nil, ErrInvalidPort
}
result.Ports = append(result.Ports, uint16(port))
}
}
return result, nil
}