mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 17:04:02 +03:00
Rename dialers into network
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
doh "github.com/babolivier/go-doh-client"
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
HTTP http.Client
|
||||
DNS doh.Resolver
|
||||
|
||||
dialer Dialer
|
||||
}
|
||||
|
||||
func (d *Network) Dial(network, address string) (net.Conn, error) {
|
||||
return d.DialContext(context.Background(), network, address)
|
||||
}
|
||||
|
||||
func (d *Network) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
host, port, _ := net.SplitHostPort(address)
|
||||
|
||||
ips, err := d.resolveIPs(network, host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot resolve dns names: %w", err)
|
||||
}
|
||||
|
||||
rand.Shuffle(len(ips), func(i, j int) {
|
||||
ips[i], ips[j] = ips[j], ips[i]
|
||||
})
|
||||
|
||||
for _, v := range ips {
|
||||
if conn, err := d.dialer.DialContext(ctx, network, net.JoinHostPort(v, port)); err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("cannot dial to %s:%s", network, address)
|
||||
}
|
||||
|
||||
func (d *Network) resolveIPs(network, address string) ([]string, error) {
|
||||
if net.ParseIP(address) != nil {
|
||||
return []string{address}, nil
|
||||
}
|
||||
|
||||
var ips []string
|
||||
|
||||
switch network {
|
||||
case "tcp", "tcp4":
|
||||
if recs, _, err := d.DNS.LookupA(address); err == nil {
|
||||
for _, v := range recs {
|
||||
ips = append(ips, v.IP4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch network {
|
||||
case "tcp", "tcp6":
|
||||
if recs, _, err := d.DNS.LookupAAAA(address); err == nil {
|
||||
for _, v := range recs {
|
||||
ips = append(ips, v.IP6)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(ips) == 0 {
|
||||
return nil, fmt.Errorf("cannot find any ips for %s:%s", network, address)
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func NewNetwork(dialer Dialer, dohHostname string, httpTimeout time.Duration) (*Network, error) {
|
||||
switch {
|
||||
case httpTimeout < 0:
|
||||
return nil, fmt.Errorf("timeout should be positive number %v", httpTimeout)
|
||||
case httpTimeout == 0:
|
||||
httpTimeout = DefaultHTTPTimeout
|
||||
}
|
||||
|
||||
if net.ParseIP(dohHostname) == nil {
|
||||
return nil, fmt.Errorf("hostname %s should be IP address", dohHostname)
|
||||
}
|
||||
|
||||
dohHTTPClient := &http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: &http.Transport{
|
||||
DialContext: dialer.DialContext,
|
||||
},
|
||||
}
|
||||
network := &Network{
|
||||
dialer: dialer,
|
||||
DNS: doh.Resolver{
|
||||
Host: dohHostname,
|
||||
Class: doh.IN,
|
||||
HTTPClient: dohHTTPClient,
|
||||
},
|
||||
}
|
||||
network.HTTP = http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: &http.Transport{
|
||||
DialContext: network.DialContext,
|
||||
},
|
||||
}
|
||||
|
||||
return network, nil
|
||||
}
|
||||
Reference in New Issue
Block a user