File size: 2,400 Bytes
bb9df9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package node

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"
)

type HY struct {
	Host     string
	Port     int
	Insecure int
	Peer     string
	Auth     string
	UpMbps   int
	DownMbps int
	ALPN     []string
	Name     string
}

// 开发者测试 CallHy 调用
func CallHy() {
	hy := HY{
		Host:     "qq.com",
		Port:     11926,
		Insecure: 1,
		Peer:     "youku.com",
		Auth:     "",
		UpMbps:   11,
		DownMbps: 55,
		// ALPN:     "h3",
	}
	fmt.Println(EncodeHYURL(hy))
}

// hy 编码
func EncodeHYURL(hy HY) string {
	// 如果没有设置 Name,则使用 Host:Port 作为 Fragment
	if hy.Name == "" {
		hy.Name = fmt.Sprintf("%s:%d", hy.Host, hy.Port)
	}
	u := url.URL{
		Scheme:   "hysteria",
		Host:     fmt.Sprintf("%s:%d", hy.Host, hy.Port),
		Fragment: hy.Name,
	}
	q := u.Query()
	q.Set("insecure", strconv.Itoa(hy.Insecure))
	q.Set("peer", hy.Peer)
	q.Set("auth", hy.Auth)
	q.Set("upmbps", strconv.Itoa(hy.UpMbps))
	q.Set("downmbps", strconv.Itoa(hy.DownMbps))
	// q.Set("alpn", hy.ALPN)
	// 检查query是否有空值,有的话删除
	for k, v := range q {
		if v[0] == "" {
			delete(q, k)
			// fmt.Printf("k: %v, v: %v\n", k, v)
		}
	}
	u.RawQuery = q.Encode()
	return u.String()
}

// hy 解码
func DecodeHYURL(s string) (HY, error) {
	u, err := url.Parse(s)
	if err != nil {
		return HY{}, fmt.Errorf("失败的URL: %s", s)
	}
	if u.Scheme != "hy" && u.Scheme != "hysteria" {
		return HY{}, fmt.Errorf("非hy协议: %s", s)
	}
	server := u.Hostname()
	port, _ := strconv.Atoi(u.Port())
	insecure, _ := strconv.Atoi(u.Query().Get("insecure"))
	auth := u.Query().Get("auth")
	upMbps, _ := strconv.Atoi(u.Query().Get("upmbps"))
	downMbps, _ := strconv.Atoi(u.Query().Get("downmbps"))
	alpns := u.Query().Get("alpn")
	alpn := strings.Split(alpns, ",")
	if alpns == "" {
		alpn = nil
	}
	// 如果没有设置 Name,则使用 Fragment 作为 Name
	name := u.Fragment
	if name == "" {
		name = server + ":" + u.Port()
	}
	if CheckEnvironment() {
		fmt.Println("server:", server)
		fmt.Println("port:", port)
		fmt.Println("insecure:", insecure)
		fmt.Println("auth:", auth)
		fmt.Println("upMbps:", upMbps)
		fmt.Println("downMbps:", downMbps)
		fmt.Println("alpn:", alpn)
		fmt.Println("name:", name)
	}
	return HY{
		Host:     server,
		Port:     port,
		Insecure: insecure,
		Auth:     auth,
		UpMbps:   upMbps,
		DownMbps: downMbps,
		ALPN:     alpn,
		Name:     name,
	}, nil
}