mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 00:04:02 +03:00
Change network to accept DialFunc
This commit is contained in:
+6
-16
@@ -38,8 +38,8 @@ type Access struct {
|
|||||||
Hex bool `help:"Print secret in hex encoding."`
|
Hex bool `help:"Print secret in hex encoding."`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Access) Run(cli *CLI) error {
|
func (c *Access) Run(cli *CLI, version string) error {
|
||||||
if err := c.ReadConfig(cli.Access.ConfigPath); err != nil {
|
if err := c.ReadConfig(cli.Access.ConfigPath, version); err != nil {
|
||||||
return fmt.Errorf("cannot init config: %w", err)
|
return fmt.Errorf("cannot init config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,21 +74,11 @@ func (c *Access) Run(cli *CLI) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Access) getIP(protocol string) net.IP {
|
func (c *Access) getIP(protocol string) net.IP {
|
||||||
client := c.network.MakeHTTPClient(0)
|
client := c.network.MakeHTTPClient(func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
client.Transport = &http.Transport{
|
|
||||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
||||||
return c.network.DialContext(ctx, protocol, address)
|
return c.network.DialContext(ctx, protocol, address)
|
||||||
},
|
})
|
||||||
}
|
|
||||||
|
|
||||||
c.network.PrepareHTTPClient(client)
|
resp, err := client.Get("https://ifconfig.co") // nolint: noctx
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, "https://ifconfig.co", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -98,7 +88,7 @@ func (c *Access) getIP(protocol string) net.IP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
io.Copy(ioutil.Discard, resp.Body)
|
io.Copy(ioutil.Discard, resp.Body) // nolint: errcheck
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -15,7 +15,7 @@ type base struct {
|
|||||||
conf *config.Config
|
conf *config.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *base) ReadConfig(path string) error {
|
func (b *base) ReadConfig(path, version string) error {
|
||||||
content, err := ioutil.ReadFile(path)
|
content, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot read config file: %w", err)
|
return fmt.Errorf("cannot read config file: %w", err)
|
||||||
@@ -26,7 +26,7 @@ func (b *base) ReadConfig(path string) error {
|
|||||||
return fmt.Errorf("cannot parse config: %w", err)
|
return fmt.Errorf("cannot parse config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ntw, err := b.makeNetwork(conf)
|
ntw, err := b.makeNetwork(conf, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot build a network: %w", err)
|
return fmt.Errorf("cannot build a network: %w", err)
|
||||||
}
|
}
|
||||||
@@ -37,11 +37,12 @@ func (b *base) ReadConfig(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *base) makeNetwork(conf *config.Config) (network.Network, error) {
|
func (b *base) makeNetwork(conf *config.Config, version string) (network.Network, error) {
|
||||||
tcpTimeout := conf.Network.Timeout.TCP.Value(network.DefaultTimeout)
|
tcpTimeout := conf.Network.Timeout.TCP.Value(network.DefaultTimeout)
|
||||||
idleTimeout := conf.Network.Timeout.Idle.Value(network.DefaultIdleTimeout)
|
idleTimeout := conf.Network.Timeout.Idle.Value(network.DefaultIdleTimeout)
|
||||||
dohIP := conf.Network.DOHIP.Value(net.ParseIP(network.DefaultDOHHostname)).String()
|
dohIP := conf.Network.DOHIP.Value(net.ParseIP(network.DefaultDOHHostname)).String()
|
||||||
bufferSize := conf.TCPBuffer.Value(network.DefaultBufferSize)
|
bufferSize := conf.TCPBuffer.Value(network.DefaultBufferSize)
|
||||||
|
userAgent := "mtg/" + version
|
||||||
|
|
||||||
baseDialer, err := network.NewDefaultDialer(tcpTimeout, int(bufferSize))
|
baseDialer, err := network.NewDefaultDialer(tcpTimeout, int(bufferSize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -58,14 +59,14 @@ func (b *base) makeNetwork(conf *config.Config) (network.Network, error) {
|
|||||||
|
|
||||||
switch len(proxyURLs) {
|
switch len(proxyURLs) {
|
||||||
case 0:
|
case 0:
|
||||||
return network.NewNetwork(baseDialer, dohIP, idleTimeout)
|
return network.NewNetwork(baseDialer, userAgent, dohIP, idleTimeout)
|
||||||
case 1:
|
case 1:
|
||||||
socksDialer, err := network.NewSocks5Dialer(baseDialer, proxyURLs[0])
|
socksDialer, err := network.NewSocks5Dialer(baseDialer, proxyURLs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
|
return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return network.NewNetwork(socksDialer, dohIP, idleTimeout)
|
return network.NewNetwork(socksDialer, userAgent, dohIP, idleTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
socksDialer, err := network.NewLoadBalancedSocks5Dialer(baseDialer, proxyURLs)
|
socksDialer, err := network.NewLoadBalancedSocks5Dialer(baseDialer, proxyURLs)
|
||||||
@@ -73,5 +74,5 @@ func (b *base) makeNetwork(conf *config.Config) (network.Network, error) {
|
|||||||
return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
|
return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return network.NewNetwork(socksDialer, dohIP, idleTimeout)
|
return network.NewNetwork(socksDialer, userAgent, dohIP, idleTimeout)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -1,8 +1,6 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import "github.com/alecthomas/kong"
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CLI struct {
|
type CLI struct {
|
||||||
GenerateSecret GenerateSecret `cmd help:"Generate new proxy secret"` // nolint: govet
|
GenerateSecret GenerateSecret `cmd help:"Generate new proxy secret"` // nolint: govet
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type GenerateSecret struct {
|
|||||||
Hex bool `help:"Print secret in hex encoding."`
|
Hex bool `help:"Print secret in hex encoding."`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GenerateSecret) Run(cli *CLI) error { // nolint: unparam
|
func (c *GenerateSecret) Run(cli *CLI, _ string) error {
|
||||||
secret := mtglib.GenerateSecret(cli.GenerateSecret.HostName)
|
secret := mtglib.GenerateSecret(cli.GenerateSecret.HostName)
|
||||||
|
|
||||||
if cli.GenerateSecret.Hex {
|
if cli.GenerateSecret.Hex {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func (c *TypeBytes) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TypeBytes) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c TypeBytes) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func (c *TypeDuration) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TypeDuration) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c TypeDuration) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.value.String()), nil
|
return []byte(c.value.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (c *TypeFloat) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TypeFloat) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c *TypeFloat) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (c *TypeHostPort) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TypeHostPort) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c TypeHostPort) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ type TypeHTTPPath struct {
|
|||||||
value string
|
value string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TypeHTTPPath) UnmarshalText(data []byte) error { // nolint: unparam
|
func (c *TypeHTTPPath) UnmarshalText(data []byte) error {
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
c.value = "/" + strings.Trim(string(data), "/")
|
c.value = "/" + strings.Trim(string(data), "/")
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ func (c *TypeHTTPPath) UnmarshalText(data []byte) error { // nolint: unparam
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TypeHTTPPath) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c TypeHTTPPath) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ func (c *TypeIP) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TypeIP) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c *TypeIP) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func (c *TypeMetricPrefix) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TypeMetricPrefix) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c TypeMetricPrefix) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ func (c *TypePort) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TypePort) MarshalJSON() ([]byte, error) { // nolint: unparam
|
func (c *TypePort) MarshalJSON() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func (c *TypePreferIP) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TypePreferIP) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c TypePreferIP) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.value), nil
|
return []byte(c.value), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ func (c *TypeURL) UnmarshalText(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TypeURL) MarshalText() ([]byte, error) { // nolint: unparam
|
func (c *TypeURL) MarshalText() ([]byte, error) {
|
||||||
return []byte(c.String()), nil
|
return []byte(c.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ func main() {
|
|||||||
"version": version,
|
"version": version,
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.FatalIfErrorf(ctx.Run(cli))
|
ctx.FatalIfErrorf(ctx.Run(cli, version))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
const (
|
const (
|
||||||
DefaultTimeout = 10 * time.Second
|
DefaultTimeout = 10 * time.Second
|
||||||
DefaultIdleTimeout = time.Minute
|
DefaultIdleTimeout = time.Minute
|
||||||
DefaultHTTPTimeout = 5 * time.Second
|
|
||||||
DefaultBufferSize = 4096
|
DefaultBufferSize = 4096
|
||||||
|
|
||||||
ProxyDialerOpenThreshold = 5
|
ProxyDialerOpenThreshold = 5
|
||||||
@@ -21,6 +20,7 @@ const (
|
|||||||
DefaultDOHHostname = "9.9.9.9"
|
DefaultDOHHostname = "9.9.9.9"
|
||||||
|
|
||||||
DNSTimeout = 5 * time.Second
|
DNSTimeout = 5 * time.Second
|
||||||
|
HTTPTimeout = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -28,6 +28,8 @@ var (
|
|||||||
ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
|
ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DialFunc func(ctx context.Context, protocol, address string) (net.Conn, error)
|
||||||
|
|
||||||
type Dialer interface {
|
type Dialer interface {
|
||||||
Dial(network, address string) (net.Conn, error)
|
Dial(network, address string) (net.Conn, error)
|
||||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||||
@@ -37,7 +39,6 @@ type Network interface {
|
|||||||
Dialer
|
Dialer
|
||||||
|
|
||||||
DNSResolve(network, hostname string) (ips []string, err error)
|
DNSResolve(network, hostname string) (ips []string, err error)
|
||||||
MakeHTTPClient(timeout time.Duration) *http.Client
|
MakeHTTPClient(DialFunc) *http.Client
|
||||||
IdleTimeout() time.Duration
|
IdleTimeout() time.Duration
|
||||||
PrepareHTTPClient(*http.Client)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-14
@@ -12,10 +12,22 @@ import (
|
|||||||
doh "github.com/babolivier/go-doh-client"
|
doh "github.com/babolivier/go-doh-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type networkHTTPTransport struct {
|
||||||
|
userAgent string
|
||||||
|
next http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n networkHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
req.Header.Set("User-Agent", n.userAgent)
|
||||||
|
|
||||||
|
return n.next.RoundTrip(req)
|
||||||
|
}
|
||||||
|
|
||||||
type network struct {
|
type network struct {
|
||||||
idleTimeout time.Duration
|
|
||||||
dialer Dialer
|
dialer Dialer
|
||||||
dns doh.Resolver
|
dns doh.Resolver
|
||||||
|
idleTimeout time.Duration
|
||||||
|
userAgent string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *network) Dial(protocol, address string) (net.Conn, error) {
|
func (n *network) Dial(protocol, address string) (net.Conn, error) {
|
||||||
@@ -107,23 +119,15 @@ func (n *network) IdleTimeout() time.Duration {
|
|||||||
return n.idleTimeout
|
return n.idleTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *network) MakeHTTPClient(timeout time.Duration) *http.Client {
|
func (n *network) MakeHTTPClient(dialFunc DialFunc) *http.Client {
|
||||||
if timeout <= 0 {
|
if dialFunc == nil {
|
||||||
timeout = DefaultHTTPTimeout
|
dialFunc = n.DialContext
|
||||||
}
|
}
|
||||||
|
|
||||||
return &http.Client{
|
return makeHTTPClient(n.userAgent, dialFunc)
|
||||||
Timeout: timeout,
|
|
||||||
Transport: &http.Transport{
|
|
||||||
DialContext: n.DialContext,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *network) PatchHTTPClient(_ *http.Client) {
|
func NewNetwork(dialer Dialer, userAgent, dohHostname string, idleTimeout time.Duration) (Network, error) {
|
||||||
}
|
|
||||||
|
|
||||||
func NewNetwork(dialer Dialer, dohHostname string, idleTimeout time.Duration) (Network, error) {
|
|
||||||
switch {
|
switch {
|
||||||
case idleTimeout < 0:
|
case idleTimeout < 0:
|
||||||
return nil, fmt.Errorf("timeout should be positive number %s", idleTimeout)
|
return nil, fmt.Errorf("timeout should be positive number %s", idleTimeout)
|
||||||
@@ -138,6 +142,7 @@ func NewNetwork(dialer Dialer, dohHostname string, idleTimeout time.Duration) (N
|
|||||||
return &network{
|
return &network{
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
idleTimeout: idleTimeout,
|
idleTimeout: idleTimeout,
|
||||||
|
userAgent: userAgent,
|
||||||
dns: doh.Resolver{
|
dns: doh.Resolver{
|
||||||
Host: dohHostname,
|
Host: dohHostname,
|
||||||
Class: doh.IN,
|
Class: doh.IN,
|
||||||
@@ -150,3 +155,15 @@ func NewNetwork(dialer Dialer, dohHostname string, idleTimeout time.Duration) (N
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeHTTPClient(userAgent string, dialFunc DialFunc) *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Timeout: HTTPTimeout,
|
||||||
|
Transport: networkHTTPTransport{
|
||||||
|
userAgent: userAgent,
|
||||||
|
next: &http.Transport{
|
||||||
|
DialContext: dialFunc,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/9seconds/mtg/v2/config"
|
|
||||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
func makeNetwork(conf *config.Config) (network.Network, error) {
|
|
||||||
tcpTimeout := conf.Network.Timeout.TCP.Value(network.DefaultTimeout)
|
|
||||||
idleTimeout := conf.Network.Timeout.Idle.Value(network.DefaultIdleTimeout)
|
|
||||||
dohIP := conf.Network.DOHIP.Value(net.ParseIP(network.DefaultDOHHostname)).String()
|
|
||||||
bufferSize := conf.TCPBuffer.Value(network.DefaultBufferSize)
|
|
||||||
|
|
||||||
baseDialer, err := network.NewDefaultDialer(tcpTimeout, int(bufferSize))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot build a default dialer: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyURLs := make([]*url.URL, 0, len(conf.Network.Proxies))
|
|
||||||
|
|
||||||
for _, v := range conf.Network.Proxies {
|
|
||||||
if value := v.Value(nil); value != nil {
|
|
||||||
proxyURLs = append(proxyURLs, v.Value(nil))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(proxyURLs) {
|
|
||||||
case 0:
|
|
||||||
return network.NewNetwork(baseDialer, dohIP, idleTimeout)
|
|
||||||
case 1:
|
|
||||||
socksDialer, err := network.NewSocks5Dialer(baseDialer, proxyURLs[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return network.NewNetwork(socksDialer, dohIP, idleTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
socksDialer, err := network.NewLoadBalancedSocks5Dialer(baseDialer, proxyURLs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("cannot build socks5 dialer: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return network.NewNetwork(socksDialer, dohIP, idleTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
func exhaustResponse(response *http.Response) {
|
|
||||||
io.Copy(ioutil.Discard, response.Body) // nolint: errcheck
|
|
||||||
response.Body.Close()
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user