Files
tun2socks/engine/parse.go
T
2026-01-10 02:07:46 -05:00

109 lines
2.2 KiB
Go

package engine
import (
"fmt"
"net"
"net/netip"
"net/url"
"runtime"
"strings"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/fdbased"
"github.com/xjasonlyu/tun2socks/v2/core/device/tun"
"github.com/xjasonlyu/tun2socks/v2/proxy"
)
const (
defaultDeviceType = "tun"
defaultProxyType = "socks5"
)
func parseRestAPI(s string) (*url.URL, error) {
if !strings.Contains(s, "://") {
s = fmt.Sprintf("%s://%s", "http", s)
}
u, err := url.Parse(s)
if err != nil {
return nil, err
}
addr, err := net.ResolveTCPAddr("tcp", u.Host)
if err != nil {
return nil, err
}
if addr.IP == nil {
addr.IP = net.IPv4zero /* default: 0.0.0.0 */
}
u.Host = addr.String()
switch u.Scheme {
case "http":
return u, nil
default:
return nil, fmt.Errorf("unsupported scheme: %s", u.Scheme)
}
}
func parseDevice(s string, mtu uint32) (device.Device, error) {
if !strings.Contains(s, "://") {
s = fmt.Sprintf("%s://%s", defaultDeviceType, s)
}
u, err := url.Parse(s)
if err != nil {
return nil, err
}
driver := strings.ToLower(u.Scheme)
switch driver {
case fdbased.Driver:
return parseFD(u, mtu)
case tun.Driver:
return parseTUN(u, mtu)
default:
return nil, fmt.Errorf("unsupported driver: %s", driver)
}
}
func parseFD(u *url.URL, mtu uint32) (device.Device, error) {
offset := 0
// fd offset in ios
// https://stackoverflow.com/questions/69260852/ios-network-extension-packet-parsing/69487795#69487795
if runtime.GOOS == "ios" {
offset = 4
}
return fdbased.Open(u.Host, mtu, offset)
}
func parseProxy(s string) (proxy.Proxy, error) {
if !strings.Contains(s, "://") {
s = fmt.Sprintf("%s://%s", defaultProxyType, s)
}
u, err := url.Parse(s)
if err != nil {
return nil, err
}
return proxy.Parse(u)
}
func parseMulticastGroups(s string) (multicastGroups []netip.Addr, _ error) {
for _, ip := range strings.Split(s, ",") {
if ip = strings.TrimSpace(ip); ip == "" {
continue
}
addr, err := netip.ParseAddr(ip)
if err != nil {
return nil, err
}
if !addr.IsMulticast() {
return nil, fmt.Errorf("invalid multicast IP: %s", addr)
}
multicastGroups = append(multicastGroups, addr)
}
return
}