Просмотр исходного кода

Move cli to separate package

tags/v2.0.0-rc1
9seconds 5 лет назад
Родитель
Сommit
6b28488fbd
7 измененных файлов: 114 добавлений и 58 удалений
  1. 0
    36
      cli.go
  2. 19
    10
      cli/access.go
  3. 77
    0
      cli/base.go
  4. 11
    0
      cli/cli.go
  5. 4
    4
      cli/generate_secret.go
  6. 2
    7
      main.go
  7. 1
    1
      mtglib/network/init.go

+ 0
- 36
cli.go Просмотреть файл

1
-package main
2
-
3
-import (
4
-	"fmt"
5
-	"io/ioutil"
6
-
7
-	"github.com/9seconds/mtg/v2/config"
8
-	"github.com/9seconds/mtg/v2/mtglib/network"
9
-)
10
-
11
-type cli struct {
12
-	network network.Network
13
-	conf    *config.Config
14
-}
15
-
16
-func (c *cli) ReadConfig(path string) error {
17
-    content, err := ioutil.ReadFile(path)
18
-    if err != nil {
19
-		return fmt.Errorf("cannot read config file: %w", err)
20
-    }
21
-
22
-	conf, err := config.Parse(content)
23
-	if err != nil {
24
-		return fmt.Errorf("cannot parse config: %w", err)
25
-	}
26
-
27
-	ntw, err := makeNetwork(conf)
28
-	if err != nil {
29
-		return fmt.Errorf("cannot build a network: %w", err)
30
-	}
31
-
32
-	c.conf = conf
33
-	c.network = ntw
34
-
35
-	return nil
36
-}

cli_access.go → cli/access.go Просмотреть файл

1
-package main
1
+package cli
2
 
2
 
3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
 	"encoding/json"
5
 	"encoding/json"
6
 	"fmt"
6
 	"fmt"
7
+	"io"
7
 	"io/ioutil"
8
 	"io/ioutil"
8
 	"net"
9
 	"net"
9
 	"net/http"
10
 	"net/http"
30
 	TmeQrCode string `json:"tme_qrcode"`
31
 	TmeQrCode string `json:"tme_qrcode"`
31
 }
32
 }
32
 
33
 
33
-type cliCommandAccess struct {
34
-	cli
34
+type Access struct {
35
+	base
35
 
36
 
36
 	ConfigPath string `arg required type:"existingfile" help:"Path to the configuration file." name:"config-path"` // nolint: lll, govet
37
 	ConfigPath string `arg required type:"existingfile" help:"Path to the configuration file." name:"config-path"` // nolint: lll, govet
37
 	Hex        bool   `help:"Print secret in hex encoding."`
38
 	Hex        bool   `help:"Print secret in hex encoding."`
38
 }
39
 }
39
 
40
 
40
-func (c *cliCommandAccess) Run(cli *CLI) error {
41
+func (c *Access) Run(cli *CLI) error {
41
 	if err := c.ReadConfig(cli.Access.ConfigPath); err != nil {
42
 	if err := c.ReadConfig(cli.Access.ConfigPath); err != nil {
42
 		return fmt.Errorf("cannot init config: %w", err)
43
 		return fmt.Errorf("cannot init config: %w", err)
43
 	}
44
 	}
72
 	return nil
73
 	return nil
73
 }
74
 }
74
 
75
 
75
-func (c *cliCommandAccess) getIP(protocol string) net.IP {
76
+func (c *Access) getIP(protocol string) net.IP {
76
 	client := c.network.MakeHTTPClient(0)
77
 	client := c.network.MakeHTTPClient(0)
77
 	client.Transport = &http.Transport{
78
 	client.Transport = &http.Transport{
78
 		DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
79
 		DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
80
 		},
81
 		},
81
 	}
82
 	}
82
 
83
 
83
-	c.network.PatchHTTPClient(client)
84
+	c.network.PrepareHTTPClient(client)
84
 
85
 
85
-	resp, err := client.Get("https://ifconfig.co") // nolint: bodyclose, noctx
86
+	req, err := http.NewRequest(http.MethodGet, "https://ifconfig.co", nil)
87
+	if err != nil {
88
+		panic(err)
89
+	}
90
+
91
+	resp, err := client.Do(req)
86
 	if err != nil {
92
 	if err != nil {
87
 		return nil
93
 		return nil
88
 	}
94
 	}
91
 		return nil
97
 		return nil
92
 	}
98
 	}
93
 
99
 
94
-	defer exhaustResponse(resp)
100
+	defer func() {
101
+		io.Copy(ioutil.Discard, resp.Body)
102
+		resp.Body.Close()
103
+	}()
95
 
104
 
96
 	data, err := ioutil.ReadAll(resp.Body)
105
 	data, err := ioutil.ReadAll(resp.Body)
97
 	if err != nil {
106
 	if err != nil {
101
 	return net.ParseIP(strings.TrimSpace(string(data)))
110
 	return net.ParseIP(strings.TrimSpace(string(data)))
102
 }
111
 }
103
 
112
 
104
-func (c *cliCommandAccess) makeURLs(ip net.IP, cli *CLI) *accessResponseURLs {
113
+func (c *Access) makeURLs(ip net.IP, cli *CLI) *accessResponseURLs {
105
 	if ip == nil {
114
 	if ip == nil {
106
 		return nil
115
 		return nil
107
 	}
116
 	}
140
 	return rv
149
 	return rv
141
 }
150
 }
142
 
151
 
143
-func (c *cliCommandAccess) makeQRCode(data string) string {
152
+func (c *Access) makeQRCode(data string) string {
144
 	values := url.Values{}
153
 	values := url.Values{}
145
 
154
 
146
 	values.Set("qzone", "4")
155
 	values.Set("qzone", "4")

+ 77
- 0
cli/base.go Просмотреть файл

1
+package cli
2
+
3
+import (
4
+	"fmt"
5
+	"io/ioutil"
6
+	"net"
7
+	"net/url"
8
+
9
+	"github.com/9seconds/mtg/v2/config"
10
+	"github.com/9seconds/mtg/v2/mtglib/network"
11
+)
12
+
13
+type base struct {
14
+	network network.Network
15
+	conf    *config.Config
16
+}
17
+
18
+func (b *base) ReadConfig(path string) error {
19
+	content, err := ioutil.ReadFile(path)
20
+	if err != nil {
21
+		return fmt.Errorf("cannot read config file: %w", err)
22
+	}
23
+
24
+	conf, err := config.Parse(content)
25
+	if err != nil {
26
+		return fmt.Errorf("cannot parse config: %w", err)
27
+	}
28
+
29
+	ntw, err := b.makeNetwork(conf)
30
+	if err != nil {
31
+		return fmt.Errorf("cannot build a network: %w", err)
32
+	}
33
+
34
+	b.conf = conf
35
+	b.network = ntw
36
+
37
+	return nil
38
+}
39
+
40
+func (b *base) makeNetwork(conf *config.Config) (network.Network, error) {
41
+	tcpTimeout := conf.Network.Timeout.TCP.Value(network.DefaultTimeout)
42
+	idleTimeout := conf.Network.Timeout.Idle.Value(network.DefaultIdleTimeout)
43
+	dohIP := conf.Network.DOHIP.Value(net.ParseIP(network.DefaultDOHHostname)).String()
44
+	bufferSize := conf.TCPBuffer.Value(network.DefaultBufferSize)
45
+
46
+	baseDialer, err := network.NewDefaultDialer(tcpTimeout, int(bufferSize))
47
+	if err != nil {
48
+		return nil, fmt.Errorf("cannot build a default dialer: %w", err)
49
+	}
50
+
51
+	proxyURLs := make([]*url.URL, 0, len(conf.Network.Proxies))
52
+
53
+	for _, v := range conf.Network.Proxies {
54
+		if value := v.Value(nil); value != nil {
55
+			proxyURLs = append(proxyURLs, v.Value(nil))
56
+		}
57
+	}
58
+
59
+	switch len(proxyURLs) {
60
+	case 0:
61
+		return network.NewNetwork(baseDialer, dohIP, idleTimeout)
62
+	case 1:
63
+		socksDialer, err := network.NewSocks5Dialer(baseDialer, proxyURLs[0])
64
+		if err != nil {
65
+			return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
66
+		}
67
+
68
+		return network.NewNetwork(socksDialer, dohIP, idleTimeout)
69
+	}
70
+
71
+	socksDialer, err := network.NewLoadBalancedSocks5Dialer(baseDialer, proxyURLs)
72
+	if err != nil {
73
+		return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
74
+	}
75
+
76
+	return network.NewNetwork(socksDialer, dohIP, idleTimeout)
77
+}

+ 11
- 0
cli/cli.go Просмотреть файл

1
+package cli
2
+
3
+import (
4
+	"github.com/alecthomas/kong"
5
+)
6
+
7
+type CLI struct {
8
+	GenerateSecret GenerateSecret   `cmd help:"Generate new proxy secret"` // nolint: govet
9
+	Access         Access           `cmd help:"Print access information."` // nolint: govet
10
+	Version        kong.VersionFlag `help:"Print version."`
11
+}

cli_generate_secret.go → cli/generate_secret.go Просмотреть файл

1
-package main
1
+package cli
2
 
2
 
3
 import (
3
 import (
4
 	"fmt"
4
 	"fmt"
6
 	"github.com/9seconds/mtg/v2/mtglib"
6
 	"github.com/9seconds/mtg/v2/mtglib"
7
 )
7
 )
8
 
8
 
9
-type cliCommandGenerateSecret struct {
10
-	cli
9
+type GenerateSecret struct {
10
+	base
11
 
11
 
12
 	HostName string `arg optional help:"Hostname to use for domain fronting. Default is '${domain_front}'." name:"hostname" default:"${domain_front}"` // nolint: lll, govet
12
 	HostName string `arg optional help:"Hostname to use for domain fronting. Default is '${domain_front}'." name:"hostname" default:"${domain_front}"` // nolint: lll, govet
13
 	Hex      bool   `help:"Print secret in hex encoding."`
13
 	Hex      bool   `help:"Print secret in hex encoding."`
14
 }
14
 }
15
 
15
 
16
-func (c *cliCommandGenerateSecret) Run(cli *CLI) error { // nolint: unparam
16
+func (c *GenerateSecret) Run(cli *CLI) error { // nolint: unparam
17
 	secret := mtglib.GenerateSecret(cli.GenerateSecret.HostName)
17
 	secret := mtglib.GenerateSecret(cli.GenerateSecret.HostName)
18
 
18
 
19
 	if cli.GenerateSecret.Hex {
19
 	if cli.GenerateSecret.Hex {

+ 2
- 7
main.go Просмотреть файл

4
 	"math/rand"
4
 	"math/rand"
5
 	"time"
5
 	"time"
6
 
6
 
7
+	"github.com/9seconds/mtg/v2/cli"
7
 	"github.com/alecthomas/kong"
8
 	"github.com/alecthomas/kong"
8
 )
9
 )
9
 
10
 
10
 var version = "dev" // has to be set by ldflags
11
 var version = "dev" // has to be set by ldflags
11
 
12
 
12
-type CLI struct {
13
-	GenerateSecret cliCommandGenerateSecret `cmd help:"Generate new proxy secret"` // nolint: govet
14
-	Access         cliCommandAccess         `cmd help:"Print access information."` // nolint: govet
15
-	Version        kong.VersionFlag         `help:"Print version."`
16
-}
17
-
18
 func main() {
13
 func main() {
19
 	rand.Seed(time.Now().UTC().UnixNano())
14
 	rand.Seed(time.Now().UTC().UnixNano())
20
 
15
 
21
-	cli := &CLI{}
16
+	cli := &cli.CLI{}
22
 	ctx := kong.Parse(cli, kong.Vars{
17
 	ctx := kong.Parse(cli, kong.Vars{
23
 		"domain_front": "amazonaws.com",
18
 		"domain_front": "amazonaws.com",
24
 		"version":      version,
19
 		"version":      version,

+ 1
- 1
mtglib/network/init.go Просмотреть файл

39
 	DNSResolve(network, hostname string) (ips []string, err error)
39
 	DNSResolve(network, hostname string) (ips []string, err error)
40
 	MakeHTTPClient(timeout time.Duration) *http.Client
40
 	MakeHTTPClient(timeout time.Duration) *http.Client
41
 	IdleTimeout() time.Duration
41
 	IdleTimeout() time.Duration
42
-	PatchHTTPClient(*http.Client)
42
+	PrepareHTTPClient(*http.Client)
43
 }
43
 }

Загрузка…
Отмена
Сохранить