Add documentation for network

This commit is contained in:
9seconds
2021-04-05 18:46:15 +03:00
parent 0dd890a09d
commit 372c703ad6
6 changed files with 105 additions and 5 deletions
+5
View File
@@ -60,6 +60,11 @@ func (d *defaultDialer) DialContext(ctx context.Context, network, address string
return tcpConn, nil
}
// NewDefaultDialer build a new dialer which dials bypassing proxies
// etc.
//
// The most default one you can imagine. But it has tunes TCP
// connections and setups SO_REUSEPORT.
func NewDefaultDialer(timeout time.Duration, bufferSize int) (Dialer, error) {
switch {
case timeout < 0:
+58 -5
View File
@@ -1,3 +1,20 @@
// Network contains a default implementation of the network.
//
// Please see mtglib.Network interface to get some basic idea behind
// this abstraction.
//
// Some notable feature of this implementation:
//
// 1. It detaches dialer from a network. Dialer is something which
// implements a real dialer and network completes it with more higher
// level details.
//
// 2. It uses only TCP connections. Even for DNS it uses DNS-Over-HTTPS
//
// 3. It has some simple implementation of DNS cache which is good
// enough for our purpose.
//
// 4. It sets uses SO_REUSEPORT port if applicable.
package network
import (
@@ -8,23 +25,59 @@ import (
)
const (
DefaultTimeout = 10 * time.Second
DefaultHTTPTimeout = 10 * time.Second
DefaultBufferSize = 16 * 1024 // 16 kib
// DefaultTimeout is a default timeout for establishing TCP
// connection.
DefaultTimeout = 10 * time.Second
// DefaultHTTPTimeout defines a default timeout for making HTTP
// request.
DefaultHTTPTimeout = 10 * time.Second
// DefaultBufferSize defines a TCP buffer size. Both read and write, so
// for real size, please multiply this number by 2.
DefaultBufferSize = 16 * 1024 // 16 kib
// ProxyDialerOpenThreshold is used for load balancing SOCKS5 dialer
// only.
//
// This dialer uses circuit breaker with of 3 stages: OPEN,
// HALF_OPEN and CLOSED. If state is CLOSED, all requests go in
// a normal mode. If you get more that ProxyDialerOpenThreshold
// errors, circuit breaker goes into OPEN mode.
//
// When circuit breaker is in OPEN mode, it forbids all request to
// a given proxy. But after ProxyDialerHalfOpenTimeout it gives a
// second chance and opens an access for a SINGLE request. If this
// request success, then circuit breaker closes, otherwise opens
// again.
//
// When circuit breaker is closed, it clears an error states each
// ProxyDialerResetFailuresTimeout.
ProxyDialerOpenThreshold = 5
ProxyDialerHalfOpenTimeout = time.Minute
ProxyDialerResetFailuresTimeout = 10 * time.Second
// DefaultDOHHostname defines a default IP address for DOH host.
// Since mtg is simple, please pass IP address here. We do not
// have bootstrap servers here embedded.
DefaultDOHHostname = "9.9.9.9"
DNSTimeout = 5 * time.Second
// DNSTimeout defines a timeout for DNS queries.
DNSTimeout = 5 * time.Second
)
var (
ErrCircuitBreakerOpened = errors.New("circuit breaker is opened")
// ErrCircuitBreakerOpened is returned when proxy is being accessed
// but circuit breaker is opened.
ErrCircuitBreakerOpened = errors.New("circuit breaker is opened")
// ErrCannotDialWithAllProxies is returned when load balancing
// client is trying to access proxies but all of them are failed.
ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
)
// Dialer defines an interface which is required to bootstrap a network
// instance from.
type Dialer interface {
Dial(network, address string) (net.Conn, error)
DialContext(ctx context.Context, network, address string) (net.Conn, error)
+10
View File
@@ -32,6 +32,16 @@ func (l loadBalancedSocks5Dialer) DialContext(ctx context.Context, network, addr
return nil, ErrCannotDialWithAllProxies
}
// NewLoadBalancedSocks5Dialer builds a new load balancing SOCKS5
// dialer.
//
// The main difference from one which is made by NewSocks5Dialer is that
// we actually have a list of these proxies. When dial is requested,
// any proxy is picked and used. If proxy fails for some reason, we try
// another one.
//
// So, it is mostly useful if you have some routes with proxies which
// are not always online or having buggy network.
func NewLoadBalancedSocks5Dialer(baseDialer Dialer, proxyURLs []*url.URL) (Dialer, error) {
dialers := make([]Dialer, 0, len(proxyURLs))
+4
View File
@@ -115,6 +115,10 @@ func (n *network) dnsResolve(protocol, address string) ([]string, error) {
return ips, nil
}
// NewNetwork assembles an mtglib.Network compatible structure
// based on a dialer and given params.
//
// It brings simple DNS cache and DNS-Over-HTTPS when necessary.
func NewNetwork(dialer Dialer,
userAgent, dohHostname string,
httpTimeout time.Duration) (mtglib.Network, error) {
+4
View File
@@ -7,6 +7,10 @@ import (
"golang.org/x/net/proxy"
)
// NewSocks5Dialer build a new dialer from a given one (so, in theory
// you can chain here). Proxy parameters are passed with URI in a form of:
//
// socks5://[user:[password]]@host:port
func NewSocks5Dialer(baseDialer Dialer, proxyURL *url.URL) (Dialer, error) {
rv, err := proxy.FromURL(proxyURL, baseDialer)
if err != nil {