129 lines
2.7 KiB
Go
129 lines
2.7 KiB
Go
package core
|
|
|
|
// ConnectionState represents VPN connection state.
|
|
type ConnectionState int
|
|
|
|
const (
|
|
Disconnected ConnectionState = iota
|
|
Connecting
|
|
Connected
|
|
Disconnecting
|
|
Error
|
|
)
|
|
|
|
func (s ConnectionState) String() string {
|
|
switch s {
|
|
case Disconnected:
|
|
return "Disconnected"
|
|
case Connecting:
|
|
return "Connecting"
|
|
case Connected:
|
|
return "Connected"
|
|
case Disconnecting:
|
|
return "Disconnecting"
|
|
case Error:
|
|
return "Error"
|
|
default:
|
|
return "Unknown"
|
|
}
|
|
}
|
|
|
|
// ProxyLink represents a parsed VPN link (trojan://, vless://, etc.)
|
|
type ProxyLink struct {
|
|
// Protocol: trojan, vless, vmess, shadowsocks
|
|
Protocol string
|
|
// Server IP or domain
|
|
Address string
|
|
// Server port
|
|
Port int
|
|
// Password (trojan) or UUID (vless/vmess)
|
|
Credential string
|
|
// Security type: reality, tls, none
|
|
Security string
|
|
// Server Name Indication for TLS/REALITY
|
|
Sni string
|
|
// TLS fingerprint (chrome, firefox, safari, etc.)
|
|
Fingerprint string
|
|
// REALITY public key
|
|
PublicKey string
|
|
// REALITY short ID
|
|
ShortId string
|
|
// Transport type: tcp, grpc, ws, h2, xhttp
|
|
Transport string
|
|
// gRPC service name
|
|
ServiceName string
|
|
// WebSocket/HTTP2 path
|
|
Path string
|
|
// Host header for WebSocket/HTTP2
|
|
Host string
|
|
// Server name from link fragment (#remark)
|
|
Remark string
|
|
// XTLS Flow (e.g. xtls-rprx-vision)
|
|
Flow string
|
|
}
|
|
|
|
func (p *ProxyLink) String() string {
|
|
return "[" + p.Protocol + "] " + p.Remark + " (" + p.Address + ":" + itoa(p.Port) + ") security=" + p.Security + " transport=" + p.Transport
|
|
}
|
|
|
|
// VpnConfig represents a saved VPN configuration.
|
|
type VpnConfig struct {
|
|
ID string `json:"Id"`
|
|
Name string `json:"Name"`
|
|
Link string `json:"Link"`
|
|
}
|
|
|
|
func (c *VpnConfig) DisplayName() string {
|
|
if c.Name == "" {
|
|
return "Unknown Server"
|
|
}
|
|
return c.Name
|
|
}
|
|
|
|
func (c *VpnConfig) ProtocolType() string {
|
|
if len(c.Link) < 5 {
|
|
return "UNKNOWN"
|
|
}
|
|
switch {
|
|
case hasPrefix(c.Link, "vless://"):
|
|
return "VLESS"
|
|
case hasPrefix(c.Link, "trojan://"):
|
|
return "TROJAN"
|
|
case hasPrefix(c.Link, "hy2://"):
|
|
return "HYSTERIA2"
|
|
case hasPrefix(c.Link, "ss://"):
|
|
return "SHADOWSOCKS"
|
|
default:
|
|
return "UNKNOWN"
|
|
}
|
|
}
|
|
|
|
// ExtractNameFromLink extracts server name from a VPN link.
|
|
func ExtractNameFromLink(link string) string {
|
|
if link == "" {
|
|
return "New Config"
|
|
}
|
|
idx := lastIndexOf(link, '#')
|
|
if idx >= 0 && idx < len(link)-1 {
|
|
encoded := link[idx+1:]
|
|
decoded, err := urlUnescape(encoded)
|
|
if err != nil {
|
|
return encoded
|
|
}
|
|
return decoded
|
|
}
|
|
parts := splitAt(link, '@')
|
|
if len(parts) > 1 {
|
|
addrPart := parts[1]
|
|
for i, ch := range addrPart {
|
|
if ch == '?' || ch == ':' || ch == '/' || ch == '#' {
|
|
if i > 0 {
|
|
return addrPart[:i]
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return "Custom Config"
|
|
}
|