69 lines
1.3 KiB
Go
69 lines
1.3 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type tunnel struct {
|
|
Network []string `yaml:"network"`
|
|
Address string `yaml:"address"`
|
|
Target string `yaml:"target"`
|
|
Proxy string `yaml:"proxy"`
|
|
}
|
|
|
|
type Tunnel tunnel
|
|
|
|
// UnmarshalYAML implements yaml.Unmarshaler
|
|
func (t *Tunnel) UnmarshalYAML(unmarshal func(any) error) error {
|
|
var tp string
|
|
if err := unmarshal(&tp); err != nil {
|
|
var inner tunnel
|
|
if err := unmarshal(&inner); err != nil {
|
|
return err
|
|
}
|
|
|
|
*t = Tunnel(inner)
|
|
return nil
|
|
}
|
|
|
|
// parse udp/tcp,address,target,proxy
|
|
parts := lo.Map(strings.Split(tp, ","), func(s string, _ int) string {
|
|
return strings.TrimSpace(s)
|
|
})
|
|
if len(parts) != 3 && len(parts) != 4 {
|
|
return fmt.Errorf("invalid tunnel config %s", tp)
|
|
}
|
|
network := strings.Split(parts[0], "/")
|
|
|
|
// validate network
|
|
for _, n := range network {
|
|
switch n {
|
|
case "tcp", "udp":
|
|
default:
|
|
return fmt.Errorf("invalid tunnel network %s", n)
|
|
}
|
|
}
|
|
|
|
// validate address and target
|
|
address := parts[1]
|
|
target := parts[2]
|
|
for _, addr := range []string{address, target} {
|
|
if _, _, err := net.SplitHostPort(addr); err != nil {
|
|
return fmt.Errorf("invalid tunnel target or address %s", addr)
|
|
}
|
|
}
|
|
|
|
*t = Tunnel(tunnel{
|
|
Network: network,
|
|
Address: address,
|
|
Target: target,
|
|
})
|
|
if len(parts) == 4 {
|
|
t.Proxy = parts[3]
|
|
}
|
|
return nil
|
|
}
|