Browse Source

Update docs

tags/v2.1.7^2
9seconds 3 years ago
parent
commit
6a19ded78e

+ 8
- 8
antireplay/init.go View File

1
-// Antireplay package has cache implementations that are effective
2
-// against replay attacks.
1
+// Antireplay package has cache implementations that are effective against
2
+// replay attacks.
3
 //
3
 //
4
-// To understand more about replay attacks, please read documentation
5
-// for mtglib.AntiReplayCache interface. This package has a list of some
4
+// To understand more about replay attacks, please read documentation for
5
+// [mtglib.AntiReplayCache] interface. This package has a list of some
6
 // implementations of this interface.
6
 // implementations of this interface.
7
 package antireplay
7
 package antireplay
8
 
8
 
9
 const (
9
 const (
10
-	// DefaultStableBloomFilterMaxSize is a recommended byte size for a
11
-	// stable bloom filter.
10
+	// DefaultStableBloomFilterMaxSize is a recommended byte size for a stable
11
+	// bloom filter.
12
 	DefaultStableBloomFilterMaxSize = 1024 * 1024 // 1MiB
12
 	DefaultStableBloomFilterMaxSize = 1024 * 1024 // 1MiB
13
 
13
 
14
-	// DefaultStableBloomFilterErrorRate is a recommended default error
15
-	// rate for a stable bloom filter.
14
+	// DefaultStableBloomFilterErrorRate is a recommended default error rate for a
15
+	// stable bloom filter.
16
 	DefaultStableBloomFilterErrorRate = 0.001
16
 	DefaultStableBloomFilterErrorRate = 0.001
17
 )
17
 )

+ 2
- 3
antireplay/noop.go View File

6
 
6
 
7
 func (n noop) SeenBefore(_ []byte) bool { return false }
7
 func (n noop) SeenBefore(_ []byte) bool { return false }
8
 
8
 
9
-// NewNoop returns an implementation that does nothing. A corresponding
10
-// method always returns false, so this cache accepts everything you
11
-// pass to it.
9
+// NewNoop returns an implementation that does nothing. A corresponding method
10
+// always returns false, so this cache accepts everything you pass to it.
12
 func NewNoop() mtglib.AntiReplayCache {
11
 func NewNoop() mtglib.AntiReplayCache {
13
 	return noop{}
12
 	return noop{}
14
 }
13
 }

+ 8
- 8
antireplay/stable_bloom_filter.go View File

20
 	return s.filter.TestAndAdd(digest)
20
 	return s.filter.TestAndAdd(digest)
21
 }
21
 }
22
 
22
 
23
-// NewStableBloomFilter returns an implementation of AntiReplayCache
24
-// based on stable bloom filter.
23
+// NewStableBloomFilter returns an implementation of AntiReplayCache based on
24
+// stable bloom filter.
25
 //
25
 //
26
 // http://webdocs.cs.ualberta.ca/~drafiei/papers/DupDet06Sigmod.pdf
26
 // http://webdocs.cs.ualberta.ca/~drafiei/papers/DupDet06Sigmod.pdf
27
 //
27
 //
28
-// The basic idea of a stable bloom filter is quite simple: each time
29
-// when you set a new element, you randomly reset P elements. There is a
30
-// hardcore math which proves that if you choose this P correctly, you
31
-// can maintain the same error rate for a stream of elements.
28
+// The basic idea of a stable bloom filter is quite simple: each time when you
29
+// set a new element, you randomly reset P elements. There is a hardcore math
30
+// which proves that if you choose this P correctly, you can maintain the same
31
+// error rate for a stream of elements.
32
 //
32
 //
33
 // byteSize is the number of bytes you want to give to a bloom filter.
33
 // byteSize is the number of bytes you want to give to a bloom filter.
34
-// errorRate is desired false-positive error rate. If you want to use
35
-// default values, please pass 0 for byteSize and <0 for errorRate.
34
+// errorRate is desired false-positive error rate. If you want to use default
35
+// values, please pass 0 for byteSize and <0 for errorRate.
36
 func NewStableBloomFilter(byteSize uint, errorRate float64) mtglib.AntiReplayCache {
36
 func NewStableBloomFilter(byteSize uint, errorRate float64) mtglib.AntiReplayCache {
37
 	if byteSize == 0 {
37
 	if byteSize == 0 {
38
 		byteSize = DefaultStableBloomFilterMaxSize
38
 		byteSize = DefaultStableBloomFilterMaxSize

+ 3
- 3
essentials/conns.go View File

5
 	"net"
5
 	"net"
6
 )
6
 )
7
 
7
 
8
-// CloseableReader is a reader interface that can close its reading end.
8
+// CloseableReader is an [io.Reader] interface that can close its reading end.
9
 type CloseableReader interface {
9
 type CloseableReader interface {
10
 	io.Reader
10
 	io.Reader
11
 	CloseRead() error
11
 	CloseRead() error
12
 }
12
 }
13
 
13
 
14
-// CloseableWriter is a writer that can close its writing end.
14
+// CloseableWriter is an [io.Writer] that can close its writing end.
15
 type CloseableWriter interface {
15
 type CloseableWriter interface {
16
 	io.Writer
16
 	io.Writer
17
 	CloseWrite() error
17
 	CloseWrite() error
18
 }
18
 }
19
 
19
 
20
-// Conn is an extension of net.Conn that can close its ends. This mostly
20
+// Conn is an extension of [net.Conn] that can close its ends. This mostly
21
 // implies TCP connections.
21
 // implies TCP connections.
22
 type Conn interface {
22
 type Conn interface {
23
 	net.Conn
23
 	net.Conn

+ 1
- 1
events/event_stream.go View File

9
 	"github.com/OneOfOne/xxhash"
9
 	"github.com/OneOfOne/xxhash"
10
 )
10
 )
11
 
11
 
12
-// EventStream is a default implementation of the mtglib.EventStream
12
+// EventStream is a default implementation of the [mtglib.EventStream]
13
 // interface.
13
 // interface.
14
 //
14
 //
15
 // EventStream manages a set of goroutines, observers. Main
15
 // EventStream manages a set of goroutines, observers. Main

+ 20
- 20
events/init.go View File

1
 // Events has a default implementations of EventStream for mtglib.
1
 // Events has a default implementations of EventStream for mtglib.
2
 //
2
 //
3
-// Please see documentation for mtglib.EventStream interface to get an
4
-// idea of such an abstraction. This package has implementations for the
5
-// default event stream.
3
+// Please see documentation for [mtglib.EventStream] interface to get an idea
4
+// of such an abstraction. This package has implementations for the default
5
+// event stream.
6
 //
6
 //
7
-// Default event stream has a list of its own concepts. First, all it
8
-// does is a routing of messages to known observers. It takes an event,
9
-// defines its type and pass this message to a method of the observer.
7
+// Default event stream has a list of its own concepts. First, all it does is a
8
+// routing of messages to known observers. It takes an event, defines its type
9
+// and pass this message to a method of the observer.
10
 //
10
 //
11
-// There might be many observers, but default event stream has a
12
-// guarantee though. It uses StreamID as a sharding key and guarantees
13
-// that a message with the same StreamID will be devlivered to the same
14
-// observer instance. So, each producer is guarateed to get all relevant
15
-// messages related to the same session. It is not possible that it will
16
-// get EventFinish if it has not seen EventStart for that session yet.
11
+// There might be many observers, but default event stream has a guarantee
12
+// though. It uses StreamID as a sharding key and guarantees that a message
13
+// with the same StreamID will be devlivered to the same observer instance. So,
14
+// each producer is guarateed to get all relevant messages related to the same
15
+// session. It is not possible that it will get EventFinish if it has not seen
16
+// EventStart for that session yet.
17
 package events
17
 package events
18
 
18
 
19
 import "github.com/9seconds/mtg/v2/mtglib"
19
 import "github.com/9seconds/mtg/v2/mtglib"
21
 // Observer is an instance that listens for the incoming events.
21
 // Observer is an instance that listens for the incoming events.
22
 //
22
 //
23
 // As it is said in the package description, the default event stream
23
 // As it is said in the package description, the default event stream
24
-// guarantees that all events with the same StreamID are going to be
25
-// routed to the same instance of the observer. So, there is no need
26
-// to synchronize information about streams between many observers
27
-// instances, they can have their local storage.
24
+// guarantees that all events with the same StreamID are going to be routed to
25
+// the same instance of the observer. So, there is no need to synchronize
26
+// information about streams between many observers instances, they can have
27
+// their local storage.
28
 type Observer interface {
28
 type Observer interface {
29
 	// EventStart reacts on incoming mtglib.EventStart event.
29
 	// EventStart reacts on incoming mtglib.EventStart event.
30
 	EventStart(mtglib.EventStart)
30
 	EventStart(mtglib.EventStart)
65
 
65
 
66
 // ObserverFactory creates a new instance of the observer.
66
 // ObserverFactory creates a new instance of the observer.
67
 //
67
 //
68
-// Default event stream creates a small set of goroutines to manage
69
-// incoming messages. Each message is routed to an appropriate observer
70
-// based on a sharding key, stream id. So, it is possible that an
71
-// instance of mtg will have many observer instances, not a single one.
68
+// Default event stream creates a small set of goroutines to manage incoming
69
+// messages. Each message is routed to an appropriate observer based on a
70
+// sharding key, stream id. So, it is possible that an instance of mtg will
71
+// have many observer instances, not a single one.
72
 type ObserverFactory func() Observer
72
 type ObserverFactory func() Observer

+ 2
- 0
ipblocklist/files/http.go View File

40
 	return h.url
40
 	return h.url
41
 }
41
 }
42
 
42
 
43
+// NewHTTP returns a file abstraction for HTTP/HTTPS endpoint. You also need to
44
+// provide a valid instance of [http.Client] to access it.
43
 func NewHTTP(client *http.Client, endpoint string) (File, error) {
45
 func NewHTTP(client *http.Client, endpoint string) (File, error) {
44
 	if client == nil {
46
 	if client == nil {
45
 		return nil, ErrBadHTTPClient
47
 		return nil, ErrBadHTTPClient

+ 7
- 0
ipblocklist/files/init.go View File

6
 	"io"
6
 	"io"
7
 )
7
 )
8
 
8
 
9
+// ErrBadHTTPClient is returned if given HTTP client is initialized
10
+// incorrectly.
9
 var ErrBadHTTPClient = errors.New("incorrect http client")
11
 var ErrBadHTTPClient = errors.New("incorrect http client")
10
 
12
 
13
+// File is an abstraction for a entity that can be opened in some context.
11
 type File interface {
14
 type File interface {
15
+	// Open returns an readable entity for a file. It is important to not forget
16
+	// to close it after the usage.
12
 	Open(context.Context) (io.ReadCloser, error)
17
 	Open(context.Context) (io.ReadCloser, error)
18
+
19
+	// String returns a short text description for the file
13
 	String() string
20
 	String() string
14
 }
21
 }

+ 1
- 0
ipblocklist/files/local.go View File

19
 	return l.path
19
 	return l.path
20
 }
20
 }
21
 
21
 
22
+// NewLocal returns an openable File for a path on a local file system.
22
 func NewLocal(path string) (File, error) {
23
 func NewLocal(path string) (File, error) {
23
 	if stat, err := os.Stat(path); os.IsNotExist(err) || stat.IsDir() || stat.Mode().Perm()&0o400 == 0 {
24
 	if stat, err := os.Stat(path); os.IsNotExist(err) || stat.IsDir() || stat.Mode().Perm()&0o400 == 0 {
24
 		return nil, fmt.Errorf("%s is not a readable file", path)
25
 		return nil, fmt.Errorf("%s is not a readable file", path)

+ 1
- 0
ipblocklist/files/mem.go View File

19
 	return "mem"
19
 	return "mem"
20
 }
20
 }
21
 
21
 
22
+// NewMem returns an openable file that is kept in RAM.
22
 func NewMem(networks []*net.IPNet) File {
23
 func NewMem(networks []*net.IPNet) File {
23
 	builder := strings.Builder{}
24
 	builder := strings.Builder{}
24
 
25
 

+ 14
- 12
ipblocklist/firehol.go View File

27
 // execute when ip list is updated.
27
 // execute when ip list is updated.
28
 type FireholUpdateCallback func(context.Context, int)
28
 type FireholUpdateCallback func(context.Context, int)
29
 
29
 
30
-// Firehol is IPBlocklist which uses lists from FireHOL:
30
+// Firehol is [mtglib.IPBlocklist] which uses lists from FireHOL:
31
 // https://iplists.firehol.org/
31
 // https://iplists.firehol.org/
32
 //
32
 //
33
-// It can use both local files and remote URLs. This is not necessary
34
-// that blocklists should be taken from this website, we expect only
35
-// compatible formats here.
33
+// It can use both local files and remote URLs. This is not necessary that
34
+// blocklists should be taken from this website, we expect only compatible
35
+// formats here.
36
 //
36
 //
37
 // Example of the format:
37
 // Example of the format:
38
 //
38
 //
39
-//     # this is a comment
40
-//     # to ignore
41
-//     127.0.0.1   # you can specify an IP
42
-//     10.0.0.0/8  # or cidr
39
+//	# this is a comment
40
+//	# to ignore
41
+//	127.0.0.1   # you can specify an IP
42
+//	10.0.0.0/8  # or cidr
43
 type Firehol struct {
43
 type Firehol struct {
44
 	ctx         context.Context
44
 	ctx         context.Context
45
 	ctxCancel   context.CancelFunc
45
 	ctxCancel   context.CancelFunc
78
 
78
 
79
 // Run starts a background update process.
79
 // Run starts a background update process.
80
 //
80
 //
81
-// This is a blocking method so you probably want to run it in a
82
-// goroutine.
81
+// This is a blocking method so you probably want to run it in a goroutine.
83
 func (f *Firehol) Run(updateEach time.Duration) {
82
 func (f *Firehol) Run(updateEach time.Duration) {
84
 	if updateEach == 0 {
83
 	if updateEach == 0 {
85
 		updateEach = DefaultFireholUpdateEach
84
 		updateEach = DefaultFireholUpdateEach
211
 
210
 
212
 // NewFirehol creates a new instance of FireHOL IP blocklist.
211
 // NewFirehol creates a new instance of FireHOL IP blocklist.
213
 //
212
 //
214
-// This method does not start an update process so please execute Run
215
-// when it is necessary.
213
+// This method does not start an update process so please execute Run when it
214
+// is necessary.
216
 func NewFirehol(logger mtglib.Logger, network mtglib.Network,
215
 func NewFirehol(logger mtglib.Logger, network mtglib.Network,
217
 	downloadConcurrency uint,
216
 	downloadConcurrency uint,
218
 	urls []string,
217
 	urls []string,
244
 	return NewFireholFromFiles(logger, downloadConcurrency, blocklists, updateCallback)
243
 	return NewFireholFromFiles(logger, downloadConcurrency, blocklists, updateCallback)
245
 }
244
 }
246
 
245
 
246
+// NewFirehol creates a new instance of FireHOL IP blocklist.
247
+//
248
+// This method creates this instances from a given list of files.
247
 func NewFireholFromFiles(logger mtglib.Logger,
249
 func NewFireholFromFiles(logger mtglib.Logger,
248
 	downloadConcurrency uint,
250
 	downloadConcurrency uint,
249
 	blocklists []files.File,
251
 	blocklists []files.File,

+ 5
- 5
ipblocklist/init.go View File

1
 // Package ipblocklist contains default implementation of the
1
 // Package ipblocklist contains default implementation of the
2
-// IPBlocklist for mtg.
2
+// [mtglib.IPBlocklist] for mtg.
3
 //
3
 //
4
-// Please check documentation for mtglib.IPBlocklist interface to get an
5
-// idea of this abstraction.
4
+// Please check documentation for [mtglib.IPBlocklist] interface to get an idea
5
+// of this abstraction.
6
 package ipblocklist
6
 package ipblocklist
7
 
7
 
8
 import "time"
8
 import "time"
12
 	// concurrent downloads of ip blocklists for Firehol.
12
 	// concurrent downloads of ip blocklists for Firehol.
13
 	DefaultFireholDownloadConcurrency = 1
13
 	DefaultFireholDownloadConcurrency = 1
14
 
14
 
15
-	// DefaultFireholUpdateEach defines a default time period when
16
-	// Firehol requests updates of the blocklists.
15
+	// DefaultFireholUpdateEach defines a default time period when Firehol
16
+	// requests updates of the blocklists.
17
 	DefaultFireholUpdateEach = 6 * time.Hour
17
 	DefaultFireholUpdateEach = 6 * time.Hour
18
 )
18
 )

+ 1
- 2
ipblocklist/noop.go View File

13
 func (n noop) Run(updateEach time.Duration) {}
13
 func (n noop) Run(updateEach time.Duration) {}
14
 func (n noop) Shutdown()                    {}
14
 func (n noop) Shutdown()                    {}
15
 
15
 
16
-// NewNoop returns a dummy ipblocklist which allows all incoming
17
-// connections.
16
+// NewNoop returns a dummy ipblocklist which allows all incoming connections.
18
 func NewNoop() mtglib.IPBlocklist {
17
 func NewNoop() mtglib.IPBlocklist {
19
 	return noop{}
18
 	return noop{}
20
 }
19
 }

+ 6
- 8
logger/init.go View File

1
-// Package logger has implementation of loggers for mtglib.Logger
2
-// interface.
1
+// Package logger has implementation of loggers for [mtglib.Logger] interface.
3
 //
2
 //
4
-// Please see a description of that interface to get some agreements
5
-// which are used by mtglib.
3
+// Please see a description of that interface to get some agreements which are
4
+// used by mtglib.
6
 package logger
5
 package logger
7
 
6
 
8
-// StdLikeLogger is an interface which is close to log.Logger. This is
9
-// commonly used by many 3pp tools. While mtglib itself does not need
10
-// it, it is always a good idea to support it and have a transient end
11
-// to end logging.
7
+// StdLikeLogger is an interface which is close to [log.Logger]. This is
8
+// commonly used by many 3pp tools. While mtglib itself does not need it, it is
9
+// always a good idea to support it and have a transient end to end logging.
12
 type StdLikeLogger interface {
10
 type StdLikeLogger interface {
13
 	Printf(format string, args ...interface{})
11
 	Printf(format string, args ...interface{})
14
 }
12
 }

+ 17
- 17
mtglib/events.go View File

29
 	RemoteIP net.IP
29
 	RemoteIP net.IP
30
 }
30
 }
31
 
31
 
32
-// EventConnectedToDC is emitted when mtg proxy has connected to a
33
-// Telegram server.
32
+// EventConnectedToDC is emitted when mtg proxy has connected to a Telegram
33
+// server.
34
 type EventConnectedToDC struct {
34
 type EventConnectedToDC struct {
35
 	eventBase
35
 	eventBase
36
 
36
 
37
-	// RemoteIP is an IP address of the Telegram server proxy has been
38
-	// connected to.
37
+	// RemoteIP is an IP address of the Telegram server proxy has been connected
38
+	// to.
39
 	RemoteIP net.IP
39
 	RemoteIP net.IP
40
 
40
 
41
 	// DC is an index of the datacenter proxy has been connected to.
41
 	// DC is an index of the datacenter proxy has been connected to.
49
 	// Traffic is a count of bytes which were transmitted.
49
 	// Traffic is a count of bytes which were transmitted.
50
 	Traffic uint
50
 	Traffic uint
51
 
51
 
52
-	// IsRead defines if we _read_ or _write_ to connection. A rule of
53
-	// thumb is simple: EventTraffic is bound to a remote connection. Not
54
-	// to a client one, but either to Telegram or front domain one.
52
+	// IsRead defines if we _read_ or _write_ to connection. A rule of thumb is
53
+	// simple: EventTraffic is bound to a remote connection. Not to a client one,
54
+	// but either to Telegram or front domain one.
55
 	//
55
 	//
56
-	// In the case of Telegram, isRead means that we've fetched some bytes
57
-	// from Telegram to send it to a client.
56
+	// In the case of Telegram, isRead means that we've fetched some bytes from
57
+	// Telegram to send it to a client.
58
 	//
58
 	//
59
-	// In the case of the front domain, it means that we've fetched some
60
-	// bytes from this domain to send it to a client.
59
+	// In the case of the front domain, it means that we've fetched some bytes
60
+	// from this domain to send it to a client.
61
 	IsRead bool
61
 	IsRead bool
62
 }
62
 }
63
 
63
 
66
 	eventBase
66
 	eventBase
67
 }
67
 }
68
 
68
 
69
-// EventDomainFronting is emitted when we connect to a front domain
70
-// instead of Telegram server.
69
+// EventDomainFronting is emitted when we connect to a front domain instead of
70
+// Telegram server.
71
 type EventDomainFronting struct {
71
 type EventDomainFronting struct {
72
 	eventBase
72
 	eventBase
73
 }
73
 }
74
 
74
 
75
-// EventConcurrencyLimited is emitted when connection was declined
76
-// because of the concurrency limit of the worker pool.
75
+// EventConcurrencyLimited is emitted when connection was declined because of
76
+// the concurrency limit of the worker pool.
77
 type EventConcurrencyLimited struct {
77
 type EventConcurrencyLimited struct {
78
 	eventBase
78
 	eventBase
79
 }
79
 }
80
 
80
 
81
-// EventIPBlocklisted is emitted when connection was declined because
82
-// IP address was found in IP blocklist.
81
+// EventIPBlocklisted is emitted when connection was declined because IP
82
+// address was found in IP blocklist.
83
 type EventIPBlocklisted struct {
83
 type EventIPBlocklisted struct {
84
 	eventBase
84
 	eventBase
85
 
85
 

+ 124
- 139
mtglib/init.go View File

1
 // mtglib defines a package with MTPROTO proxy.
1
 // mtglib defines a package with MTPROTO proxy.
2
 //
2
 //
3
-// Since mtg itself is build as an example of how to work with mtglib,
4
-// it worth to telling a couple of words about a project organization.
3
+// Since mtg itself is build as an example of how to work with mtglib, it worth
4
+// to telling a couple of words about a project organization.
5
 //
5
 //
6
-// A core object of the project is mtglib.Proxy. This is a proxy you
7
-// expect: that one which you configure, set to serve on a listener
8
-// and/or shutdown on application termination.
6
+// A core object of the project is [mtglib.Proxy]. This is a proxy you expect:
7
+// that one which you configure, set to serve on a listener and/or shutdown on
8
+// application termination.
9
 //
9
 //
10
-// But it also has a core logic unrelated to Telegram per se: anti
11
-// replay cache, network connectivity (who knows, maybe you want to have
12
-// a native VMESS integration) and so on.
10
+// But it also has a core logic unrelated to Telegram per se: anti replay
11
+// cache, network connectivity (who knows, maybe you want to have a native
12
+// VMESS integration) and so on.
13
 //
13
 //
14
-// You can supply such parts to a proxy with interfaces. The rest of
15
-// the packages in mtg define some default implementations of these
16
-// interfaces. But if you want to integrate it with, let say, influxdb,
17
-// you can do it easily.
14
+// You can supply such parts to a proxy with interfaces. The rest of the
15
+// packages in mtg define some default implementations of these interfaces. But
16
+// if you want to integrate it with, let say, influxdb, you can do it easily.
18
 package mtglib
17
 package mtglib
19
 
18
 
20
 import (
19
 import (
28
 )
27
 )
29
 
28
 
30
 var (
29
 var (
31
-	// ErrSecretEmpty is returned if you are trying to create a proxy
32
-	// but do not provide a secret.
30
+	// ErrSecretEmpty is returned if you are trying to create a proxy but do not
31
+	// provide a secret.
33
 	ErrSecretEmpty = errors.New("secret is empty")
32
 	ErrSecretEmpty = errors.New("secret is empty")
34
 
33
 
35
-	// ErrSecretInvalid is returned if you are trying to create a proxy
36
-	// but secret value is invalid (no host or payload are zeroes).
34
+	// ErrSecretInvalid is returned if you are trying to create a proxy but secret
35
+	// value is invalid (no host or payload are zeroes).
37
 	ErrSecretInvalid = errors.New("secret is invalid")
36
 	ErrSecretInvalid = errors.New("secret is invalid")
38
 
37
 
39
-	// ErrNetworkIsNotDefined is returned if you are trying to create a
40
-	// proxy but network value is undefined.
38
+	// ErrNetworkIsNotDefined is returned if you are trying to create a proxy but
39
+	// network value is undefined.
41
 	ErrNetworkIsNotDefined = errors.New("network is not defined")
40
 	ErrNetworkIsNotDefined = errors.New("network is not defined")
42
 
41
 
43
-	// ErrAntiReplayCacheIsNotDefined is returned if you are trying to
44
-	// create a proxy but anti replay cache value is undefined.
42
+	// ErrAntiReplayCacheIsNotDefined is returned if you are trying to create a
43
+	// proxy but anti replay cache value is undefined.
45
 	ErrAntiReplayCacheIsNotDefined = errors.New("anti-replay cache is not defined")
44
 	ErrAntiReplayCacheIsNotDefined = errors.New("anti-replay cache is not defined")
46
 
45
 
47
-	// ErrIPBlocklistIsNotDefined is returned if you are trying to
48
-	// create a proxy but ip blocklist instance is not defined.
46
+	// ErrIPBlocklistIsNotDefined is returned if you are trying to create a proxy
47
+	// but ip blocklist instance is not defined.
49
 	ErrIPBlocklistIsNotDefined = errors.New("ip blocklist is not defined")
48
 	ErrIPBlocklistIsNotDefined = errors.New("ip blocklist is not defined")
50
 
49
 
51
-	// ErrIPAllowlistIsNotDefined is returned if you are trying to
52
-	// create a proxy but ip allowlist instance is not defined.
50
+	// ErrIPAllowlistIsNotDefined is returned if you are trying to create a proxy
51
+	// but ip allowlist instance is not defined.
53
 	ErrIPAllowlistIsNotDefined = errors.New("ip allowlist is not defined")
52
 	ErrIPAllowlistIsNotDefined = errors.New("ip allowlist is not defined")
54
 
53
 
55
-	// ErrEventStreamIsNotDefined is returned if you are trying to create a
56
-	// proxy but event stream instance is not defined.
54
+	// ErrEventStreamIsNotDefined is returned if you are trying to create a proxy
55
+	// but event stream instance is not defined.
57
 	ErrEventStreamIsNotDefined = errors.New("event stream is not defined")
56
 	ErrEventStreamIsNotDefined = errors.New("event stream is not defined")
58
 
57
 
59
-	// ErrLoggerIsNotDefined is returned if you are trying to
60
-	// create a proxy but logger is not defined.
58
+	// ErrLoggerIsNotDefined is returned if you are trying to create a proxy but
59
+	// logger is not defined.
61
 	ErrLoggerIsNotDefined = errors.New("logger is not defined")
60
 	ErrLoggerIsNotDefined = errors.New("logger is not defined")
62
 )
61
 )
63
 
62
 
64
 const (
63
 const (
65
-	// DefaultConcurrency is a default max count of simultaneously
66
-	// connected clients.
64
+	// DefaultConcurrency is a default max count of simultaneously connected
65
+	// clients.
67
 	DefaultConcurrency = 4096
66
 	DefaultConcurrency = 4096
68
 
67
 
69
 	// DefaultBufferSize is a default size of a copy buffer.
68
 	// DefaultBufferSize is a default size of a copy buffer.
71
 	// Deprecated: this setting no longer makes any effect.
70
 	// Deprecated: this setting no longer makes any effect.
72
 	DefaultBufferSize = 16 * 1024 // 16 kib
71
 	DefaultBufferSize = 16 * 1024 // 16 kib
73
 
72
 
74
-	// DefaultDomainFrontingPort is a default port (HTTPS) to connect to in
75
-	// case of probe-resistance activity.
73
+	// DefaultDomainFrontingPort is a default port (HTTPS) to connect to in case
74
+	// of probe-resistance activity.
76
 	DefaultDomainFrontingPort = 443
75
 	DefaultDomainFrontingPort = 443
77
 
76
 
78
-	// DefaultIdleTimeout is a default timeout for closing a connection
79
-	// in case of idling.
77
+	// DefaultIdleTimeout is a default timeout for closing a connection in case of
78
+	// idling.
80
 	//
79
 	//
81
-	// Deprecated: no longer in use because of changed TCP relay
82
-	// algorithm.
80
+	// Deprecated: no longer in use because of changed TCP relay algorithm.
83
 	DefaultIdleTimeout = time.Minute
81
 	DefaultIdleTimeout = time.Minute
84
 
82
 
85
-	// DefaultTolerateTimeSkewness is a default timeout for time
86
-	// skewness on a faketls timeout verification.
83
+	// DefaultTolerateTimeSkewness is a default timeout for time skewness on a
84
+	// faketls timeout verification.
87
 	DefaultTolerateTimeSkewness = 3 * time.Second
85
 	DefaultTolerateTimeSkewness = 3 * time.Second
88
 
86
 
89
-	// DefaultPreferIP is a default value for Telegram IP connectivity
90
-	// preference.
87
+	// DefaultPreferIP is a default value for Telegram IP connectivity preference.
91
 	DefaultPreferIP = "prefer-ipv6"
88
 	DefaultPreferIP = "prefer-ipv6"
92
 
89
 
93
-	// SecretKeyLength defines a length of the secret bytes used
94
-	// by Telegram and a proxy.
90
+	// SecretKeyLength defines a length of the secret bytes used by Telegram and a
91
+	// proxy.
95
 	SecretKeyLength = 16
92
 	SecretKeyLength = 16
96
 
93
 
97
-	// ConnectionIDBytesLength defines a count of random bytes used to generate
98
-	// a stream/connection ids.
94
+	// ConnectionIDBytesLength defines a count of random bytes used to generate a
95
+	// stream/connection ids.
99
 	ConnectionIDBytesLength = 16
96
 	ConnectionIDBytesLength = 16
100
 
97
 
101
 	// TCPRelayReadTimeout defines a max time period between two consecuitive
98
 	// TCPRelayReadTimeout defines a max time period between two consecuitive
104
 	TCPRelayReadTimeout = 20 * time.Second
101
 	TCPRelayReadTimeout = 20 * time.Second
105
 )
102
 )
106
 
103
 
107
-// Network defines a knowledge how to work with a network. It may sound
108
-// fun but it encapsulates all the knowledge how to properly establish
109
-// connections to remote hosts and configure HTTP clients.
104
+// Network defines a knowledge how to work with a network. It may sound fun but
105
+// it encapsulates all the knowledge how to properly establish connections to
106
+// remote hosts and configure HTTP clients.
110
 //
107
 //
111
-// For example, if you want to use SOCKS5 proxy, you probably want to
112
-// have all traffic routed to this proxy: telegram connections, http
113
-// requests and so on. This knowledge is encapsulated into instances of
114
-// such interface.
108
+// For example, if you want to use SOCKS5 proxy, you probably want to have all
109
+// traffic routed to this proxy: telegram connections, http requests and so on.
110
+// This knowledge is encapsulated into instances of such interface.
115
 //
111
 //
116
 // mtglib uses Network for:
112
 // mtglib uses Network for:
117
-//
118
-// 1. Dialing to Telegram
119
-//
120
-// 2. Dialing to front domain
121
-//
122
-// 3. Doing HTTP requests (for example, for FireHOL ipblocklist).
113
+//     1. Dialing to Telegram
114
+//     2. Dialing to front domain
115
+//     3. Doing HTTP requests (for example, for FireHOL ipblocklist).
123
 type Network interface {
116
 type Network interface {
124
 	// Dial establishes context-free TCP connections.
117
 	// Dial establishes context-free TCP connections.
125
 	Dial(network, address string) (essentials.Conn, error)
118
 	Dial(network, address string) (essentials.Conn, error)
126
 
119
 
127
-	// DialContext dials using a context. This is a preferrable
128
-	// way of establishing TCP connections.
120
+	// DialContext dials using a context. This is a preferrable way of
121
+	// establishing TCP connections.
129
 	DialContext(ctx context.Context, network, address string) (essentials.Conn, error)
122
 	DialContext(ctx context.Context, network, address string) (essentials.Conn, error)
130
 
123
 
131
-	// MakeHTTPClient build an HTTP client with given dial function. If
132
-	// nothing is provided, then DialContext of this interface is going
133
-	// to be used.
124
+	// MakeHTTPClient build an HTTP client with given dial function. If nothing is
125
+	// provided, then DialContext of this interface is going to be used.
134
 	MakeHTTPClient(func(ctx context.Context, network, address string) (essentials.Conn, error)) *http.Client
126
 	MakeHTTPClient(func(ctx context.Context, network, address string) (essentials.Conn, error)) *http.Client
135
 }
127
 }
136
 
128
 
137
-// AntiReplayCache is an interface that is used to detect replay attacks
138
-// based on some traffic fingerprints.
129
+// AntiReplayCache is an interface that is used to detect replay attacks based
130
+// on some traffic fingerprints.
139
 //
131
 //
140
-// Replay attacks are probe attacks whose main goal is to identify if
141
-// server software can be classified in some way. For example, if you
142
-// send some HTTP request to a web server, then you can expect that this
143
-// server will respond with HTTP response back.
132
+// Replay attacks are probe attacks whose main goal is to identify if server
133
+// software can be classified in some way. For example, if you send some HTTP
134
+// request to a web server, then you can expect that this server will respond
135
+// with HTTP response back.
144
 //
136
 //
145
-// There is a problem though. Let's imagine, that connection is
146
-// encrypted. Let's imagine, that it is encrypted with some static key
147
-// like ShadowSocks (https://shadowsocks.org/assets/whitepaper.pdf).
148
-// In that case, in theory, if you repeat the same bytes, you can get
149
-// the same responses. Let's imagine, that you've cracked the key. then
150
-// if you send the same bytes, you can decrypt a response and see its
151
-// structure. Based on its structure you can identify if this server is
152
-// SOCKS5, MTPROTO proxy etc.
137
+// There is a problem though. Let's imagine, that connection is encrypted.
138
+// Let's imagine, that it is encrypted with some static key like [ShadowSocks].
139
+// In that case, in theory, if you repeat the same bytes, you can get the same
140
+// responses. Let's imagine, that you've cracked the key. then if you send the
141
+// same bytes, you can decrypt a response and see its structure. Based on its
142
+// structure you can identify if this server is SOCKS5, MTPROTO proxy etc.
153
 //
143
 //
154
-// This is just one example, maybe not the best or not the most
155
-// relevant. In real life, different organizations use such replay
156
-// attacks to perform some reverse engineering of the proxy, do some
157
-// statical analysis to identify server software.
144
+// This is just one example, maybe not the best or not the most relevant. In
145
+// real life, different organizations use such replay attacks to perform some
146
+// reverse engineering of the proxy, do some statical analysis to identify
147
+// server software.
158
 //
148
 //
159
-// There are many ways how to protect your proxy against them. One
160
-// is domain fronting which is a core part of mtg. Another one is to
161
-// collect some 'handshake fingerprints' and forbid duplication.
149
+// There are many ways how to protect your proxy against them. One is domain
150
+// fronting which is a core part of mtg. Another one is to collect some
151
+// 'handshake fingerprints' and forbid duplication.
162
 //
152
 //
163
-// So, it one is sending the same byte flow right after you (or a couple
164
-// of hours after), mtg should detect that and reject this connection
165
-// (or redirect to fronting domain).
153
+// So, it one is sending the same byte flow right after you (or a couple of
154
+// hours after), mtg should detect that and reject this connection (or redirect
155
+// to fronting domain).
156
+//
157
+// [ShadowSocks]: https://shadowsocks.org/assets/whitepaper.pdf
166
 type AntiReplayCache interface {
158
 type AntiReplayCache interface {
167
-	// Seen before checks if this set of bytes was observed before or
168
-	// not. If it is required to store this information somewhere else,
169
-	// then it has to do that.
159
+	// Seen before checks if this set of bytes was observed before or not. If it
160
+	// is required to store this information somewhere else, then it has to do
161
+	// that.
170
 	SeenBefore(data []byte) bool
162
 	SeenBefore(data []byte) bool
171
 }
163
 }
172
 
164
 
173
 // IPBlocklist filters requests based on IP address.
165
 // IPBlocklist filters requests based on IP address.
174
 //
166
 //
175
-// If this filter has an IP address, then mtg closes a request without
176
-// reading anything from a socket. It also does not give such request to
177
-// a worker pool, so in worst cases you can expect that you invoke this
178
-// object more frequent than defined proxy concurrency.
167
+// If this filter has an IP address, then mtg closes a request without reading
168
+// anything from a socket. It also does not give such request to a worker pool,
169
+// so in worst cases you can expect that you invoke this object more frequent
170
+// than defined proxy concurrency.
179
 type IPBlocklist interface {
171
 type IPBlocklist interface {
180
-	// Contains checks if given IP address belongs to this blocklist If.
181
-	// it is, a connection is terminated                               .
172
+	// Contains checks if given IP address belongs to this blocklist If. it is, a
173
+	// connection is terminated .
182
 	Contains(net.IP) bool
174
 	Contains(net.IP) bool
183
 
175
 
184
 	// Run starts a background update procedure for a blocklist
176
 	// Run starts a background update procedure for a blocklist
188
 	Shutdown()
180
 	Shutdown()
189
 }
181
 }
190
 
182
 
191
-// Event is a data structure which is populated during mtg request
192
-// processing lifecycle. Each request popluates many events:
193
-//
194
-// 1. Client connected
183
+// Event is a data structure which is populated during mtg request processing
184
+// lifecycle. Each request popluates many events:
185
+//  1. Client connected
186
+//  2. Request is finished
187
+//  3. Connection to Telegram server is established
195
 //
188
 //
196
-// 2. Request is finished
197
-//
198
-// 3. Connection to Telegram server is established
199
-//
200
-// and so on. All these events are data structures but all of them
201
-// must conform the same interface.
189
+// and so on. All these events are data structures but all of them must conform
190
+// the same interface.
202
 type Event interface {
191
 type Event interface {
203
-	// StreamID returns an identifier of the stream, connection,
204
-	// request, you name it. All events within the same stream returns
205
-	// the same stream id.
192
+	// StreamID returns an identifier of the stream, connection, request, you name
193
+	// it. All events within the same stream returns the same stream id.
206
 	StreamID() string
194
 	StreamID() string
207
 
195
 
208
 	// Timestamp returns a timestamp when this event was generated.
196
 	// Timestamp returns a timestamp when this event was generated.
209
 	Timestamp() time.Time
197
 	Timestamp() time.Time
210
 }
198
 }
211
 
199
 
212
-// EventStream is an abstraction that accepts a set of events produced
213
-// by mtg. Its main goal is to inject your logging or monitoring system.
200
+// EventStream is an abstraction that accepts a set of events produced by mtg.
201
+// Its main goal is to inject your logging or monitoring system.
214
 //
202
 //
215
-// The idea is simple. When mtg works, it emits a set of events during
216
-// a lifecycle of the requestor: EventStart, EventFinish etc. mtg is a
217
-// producer which puts these events into a stream. Responsibility of
218
-// the stream is to deliver this event to consumers/observers. There
219
-// might be many different observers (for example, you want to have both
220
-// statsd and prometheus), mtg should know nothing about them.
203
+// The idea is simple. When mtg works, it emits a set of events during a
204
+// lifecycle of the requestor: EventStart, EventFinish etc. mtg is a producer
205
+// which puts these events into a stream. Responsibility of the stream is to
206
+// deliver this event to consumers/observers. There might be many different
207
+// observers (for example, you want to have both statsd and prometheus), mtg
208
+// should know nothing about them.
221
 type EventStream interface {
209
 type EventStream interface {
222
-	// Send delivers an event to observers. Given context has to be
223
-	// respected. If the context is closed, all blocking operations should
224
-	// be released ASAP.
210
+	// Send delivers an event to observers. Given context has to be respected. If
211
+	// the context is closed, all blocking operations should be released ASAP.
225
 	//
212
 	//
226
 	// It is possible that context is closed but the message is delivered.
213
 	// It is possible that context is closed but the message is delivered.
227
 	// EventStream implementations should solve this issue somehow.
214
 	// EventStream implementations should solve this issue somehow.
230
 
217
 
231
 // Logger defines an interface of the logger used by mtglib.
218
 // Logger defines an interface of the logger used by mtglib.
232
 //
219
 //
233
-// Each logger has a name. It is possible to stack names to organize
234
-// poor-man namespaces. Also, each logger must be able to bind
235
-// parameters to avoid pushing them all the time.
220
+// Each logger has a name. It is possible to stack names to organize poor-man
221
+// namespaces. Also, each logger must be able to bind parameters to avoid
222
+// pushing them all the time.
236
 //
223
 //
237
 // Example
224
 // Example
238
 //
225
 //
239
-//     logger := SomeLogger{}
240
-//     logger = logger.BindStr("ip", net.IP{127, 0, 0, 1})
241
-//     logger.Info("Hello")
226
+//	logger := SomeLogger{} logger = logger.BindStr("ip", net.IP{127, 0, 0, 1})
227
+//	logger.Info("Hello")
242
 //
228
 //
243
-// In that case, ip is bound as a parameter. It is a great idea to
244
-// put this parameter somewhere in a log message.
229
+// In that case, ip is bound as a parameter. It is a great idea to put this
230
+// parameter somewhere in a log message.
245
 //
231
 //
246
-//     logger1 = logger.BindStr("param1", "11")
247
-//     logger2 = logger.BindInt("param2", 11)
232
+//	logger1 = logger.BindStr("param1", "11") logger2 = logger.BindInt("param2",
233
+//	11)
248
 //
234
 //
249
 // logger1 should see no param2 and vice versa, logger2 should not see param1
235
 // logger1 should see no param2 and vice versa, logger2 should not see param1
250
 // If you attach a parameter to a logger, parents should not know about that.
236
 // If you attach a parameter to a logger, parents should not know about that.
251
 type Logger interface {
237
 type Logger interface {
252
-	// Named returns a new logger with a bound name. Name chaining is
253
-	// allowed and appreciated.
238
+	// Named returns a new logger with a bound name. Name chaining is allowed and
239
+	// appreciated.
254
 	Named(name string) Logger
240
 	Named(name string) Logger
255
 
241
 
256
 	// BindInt binds new integer parameter to a new logger instance.
242
 	// BindInt binds new integer parameter to a new logger instance.
268
 	// Info puts a message about some normal situation.
254
 	// Info puts a message about some normal situation.
269
 	Info(msg string)
255
 	Info(msg string)
270
 
256
 
271
-	// InfoError puts a message about some normal situation but this
272
-	// situation is related to a given error.
257
+	// InfoError puts a message about some normal situation but this situation is
258
+	// related to a given error.
273
 	InfoError(msg string, err error)
259
 	InfoError(msg string, err error)
274
 
260
 
275
-	// Warning puts a message about some extraordinary situation
276
-	// worth to look at.
261
+	// Warning puts a message about some extraordinary situation worth to look at.
277
 	Warning(msg string)
262
 	Warning(msg string)
278
 
263
 
279
-	// WarningError puts a message about some extraordinary situation
280
-	// worth to look at. This situation is related to a given error.
264
+	// WarningError puts a message about some extraordinary situation worth to
265
+	// look at. This situation is related to a given error.
281
 	WarningError(msg string, err error)
266
 	WarningError(msg string, err error)
282
 
267
 
283
 	// Debug puts a message useful for debugging only.
268
 	// Debug puts a message useful for debugging only.
284
 	Debug(msg string)
269
 	Debug(msg string)
285
 
270
 
286
-	// Debug puts a message useful for debugging only. This message is
287
-	// related to a given error.
271
+	// Debug puts a message useful for debugging only. This message is related to
272
+	// a given error.
288
 	DebugError(msg string, err error)
273
 	DebugError(msg string, err error)
289
 }
274
 }

+ 4
- 4
mtglib/proxy.go View File

44
 	return net.JoinHostPort(p.secret.Host, strconv.Itoa(p.domainFrontingPort))
44
 	return net.JoinHostPort(p.secret.Host, strconv.Itoa(p.domainFrontingPort))
45
 }
45
 }
46
 
46
 
47
-// ServeConn serves a connection. We do not check IP blocklist and
48
-// concurrency limit here.
47
+// ServeConn serves a connection. We do not check IP blocklist and concurrency
48
+// limit here.
49
 func (p *Proxy) ServeConn(conn essentials.Conn) {
49
 func (p *Proxy) ServeConn(conn essentials.Conn) {
50
 	p.streamWaitGroup.Add(1)
50
 	p.streamWaitGroup.Add(1)
51
 	defer p.streamWaitGroup.Done()
51
 	defer p.streamWaitGroup.Done()
138
 	}
138
 	}
139
 }
139
 }
140
 
140
 
141
-// Shutdown 'gracefully' shutdowns all connections. Please remember that
142
-// it does not close an underlying listener.
141
+// Shutdown 'gracefully' shutdowns all connections. Please remember that it
142
+// does not close an underlying listener.
143
 func (p *Proxy) Shutdown() {
143
 func (p *Proxy) Shutdown() {
144
 	p.ctxCancel()
144
 	p.ctxCancel()
145
 	p.streamWaitGroup.Wait()
145
 	p.streamWaitGroup.Wait()

+ 25
- 29
mtglib/proxy_opts.go View File

4
 
4
 
5
 // ProxyOpts is a structure with settings to mtg proxy.
5
 // ProxyOpts is a structure with settings to mtg proxy.
6
 //
6
 //
7
-// This is not required per se, but this is to shorten function
8
-// signature and give an ability to conveniently provide default values.
7
+// This is not required per se, but this is to shorten function signature and
8
+// give an ability to conveniently provide default values.
9
 type ProxyOpts struct {
9
 type ProxyOpts struct {
10
 	// Secret defines a secret which should be used by a proxy.
10
 	// Secret defines a secret which should be used by a proxy.
11
 	//
11
 	//
12
 	// This is a mandatory setting.
12
 	// This is a mandatory setting.
13
 	Secret Secret
13
 	Secret Secret
14
 
14
 
15
-	// Network defines a network instance which should be used for all
16
-	// network communications made by proxies.
15
+	// Network defines a network instance which should be used for all network
16
+	// communications made by proxies.
17
 	//
17
 	//
18
 	// This is a mandatory setting.
18
 	// This is a mandatory setting.
19
 	Network Network
19
 	Network Network
45
 
45
 
46
 	// BufferSize is a size of the copy buffer in bytes.
46
 	// BufferSize is a size of the copy buffer in bytes.
47
 	//
47
 	//
48
-	// Please remember that we multiply this number in 2, because when
49
-	// we relay between proxies, we have to create 2 intermediate
50
-	// buffers: to and from.
48
+	// Please remember that we multiply this number in 2, because when we relay
49
+	// between proxies, we have to create 2 intermediate buffers: to and from.
51
 	//
50
 	//
52
 	// This is an optional setting.
51
 	// This is an optional setting.
53
 	//
52
 	//
62
 	// This is an optional setting.
61
 	// This is an optional setting.
63
 	Concurrency uint
62
 	Concurrency uint
64
 
63
 
65
-	// IdleTimeout is a timeout for relay when we have to break a
66
-	// stream.
64
+	// IdleTimeout is a timeout for relay when we have to break a stream.
67
 	//
65
 	//
68
-	// This is a timeout for any activity. So, if we have any message
69
-	// which will pass to either direction, a timer is reset. If we have
70
-	// no any reads or writes for this timeout, a connection will be
71
-	// aborted.
66
+	// This is a timeout for any activity. So, if we have any message which will
67
+	// pass to either direction, a timer is reset. If we have no any reads or
68
+	// writes for this timeout, a connection will be aborted.
72
 	//
69
 	//
73
 	// This is an optional setting.
70
 	// This is an optional setting.
74
 	IdleTimeout time.Duration
71
 	IdleTimeout time.Duration
75
 
72
 
76
-	// TolerateTimeSkewness is a time boundary that defines a time
77
-	// range where faketls timestamp is acceptable.
73
+	// TolerateTimeSkewness is a time boundary that defines a time range where
74
+	// faketls timestamp is acceptable.
78
 	//
75
 	//
79
-	// This means that if if you got a timestamp X, now is Y, then
80
-	// if |X-Y| < TolerateTimeSkewness, then you accept a packet.
76
+	// This means that if if you got a timestamp X, now is Y, then if |X-Y| <
77
+	// TolerateTimeSkewness, then you accept a packet.
81
 	//
78
 	//
82
 	// This is an optional setting.
79
 	// This is an optional setting.
83
 	TolerateTimeSkewness time.Duration
80
 	TolerateTimeSkewness time.Duration
88
 	// This is an optional setting.
85
 	// This is an optional setting.
89
 	PreferIP string
86
 	PreferIP string
90
 
87
 
91
-	// DomainFrontingPort is a port we use to connect to a fronting
92
-	// domain.
88
+	// DomainFrontingPort is a port we use to connect to a fronting domain.
93
 	//
89
 	//
94
-	// This is required because secret does not specify a port. It
95
-	// specifies a hostname only.
90
+	// This is required because secret does not specify a port. It specifies a
91
+	// hostname only.
96
 	//
92
 	//
97
 	// This is an optional setting.
93
 	// This is an optional setting.
98
 	DomainFrontingPort uint
94
 	DomainFrontingPort uint
99
 
95
 
100
 	// AllowFallbackOnUnknownDC defines how proxy behaves if unknown DC was
96
 	// AllowFallbackOnUnknownDC defines how proxy behaves if unknown DC was
101
-	// requested. If this setting is set to false, then such connection
102
-	// will be rejected. Otherwise, proxy will chose any DC.
97
+	// requested. If this setting is set to false, then such connection will be
98
+	// rejected. Otherwise, proxy will chose any DC.
103
 	//
99
 	//
104
-	// Telegram is designed in a way that any DC can serve any request,
105
-	// the problem is a latency.
100
+	// Telegram is designed in a way that any DC can serve any request, the
101
+	// problem is a latency.
106
 	//
102
 	//
107
 	// This is an optional setting.
103
 	// This is an optional setting.
108
 	AllowFallbackOnUnknownDC bool
104
 	AllowFallbackOnUnknownDC bool
109
 
105
 
110
-	// UseTestDCs defines if we have to connect to production or to staging
111
-	// DCs of Telegram.
106
+	// UseTestDCs defines if we have to connect to production or to staging DCs of
107
+	// Telegram.
112
 	//
108
 	//
113
-	// This is required if you use mtglib as an integration library for
114
-	// your Telegram-related projects.
109
+	// This is required if you use mtglib as an integration library for your
110
+	// Telegram-related projects.
115
 	//
111
 	//
116
 	// This is an optional setting.
112
 	// This is an optional setting.
117
 	UseTestDCs bool
113
 	UseTestDCs bool

+ 17
- 18
mtglib/secret.go View File

17
 // "ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d".
17
 // "ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d".
18
 // Actually, this is a serialized datastructure of 2 parts: key and host.
18
 // Actually, this is a serialized datastructure of 2 parts: key and host.
19
 //
19
 //
20
-//     ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d
21
-//     |-|-------------------------------|-------------------------------------------
22
-//     p key                             hostname
20
+//	ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d
21
+//	|-|-------------------------------|-------------------------------------------
22
+//	p key                             hostname
23
 //
23
 //
24
-// Serialized secret starts with 'ee'. Actually, in the past we also had
25
-// 'dd' secrets and prefixless ones. But this is history. Currently,
26
-// we do have only 'ee' secrets which mean faketls + protection from
27
-// statistical attacks on a length. 'ee' is a byte 238 (0xee).
24
+// Serialized secret starts with 'ee'. Actually, in the past we also had 'dd'
25
+// secrets and prefixless ones. But this is history. Currently, we do have only
26
+// 'ee' secrets which mean faketls + protection from statistical attacks on a
27
+// length. 'ee' is a byte 238 (0xee).
28
 //
28
 //
29
-// After that, we have 16 bytes of the key. This is a random generated
30
-// secret data of the proxy and this data is used to derive
31
-// authentication schemas. These secrets are mixed into hmacs and sha256
32
-// checksums which are used to build AEAD ciphers for obfuscated2
33
-// protocol and ensure faketls handshake.
29
+// After that, we have 16 bytes of the key. This is a random generated secret
30
+// data of the proxy and this data is used to derive authentication schemas.
31
+// These secrets are mixed into hmacs and sha256 checksums which are used to
32
+// build AEAD ciphers for obfuscated2 protocol and ensure faketls handshake.
34
 //
33
 //
35
-// Host is a domain fronting hostname in latin1 (ASCII) encoding. This
36
-// hostname should be used for SNI in faketls and MTG verifies it. Also,
37
-// this is when mtg gets about a domain fronting hostname.
34
+// Host is a domain fronting hostname in latin1 (ASCII) encoding. This hostname
35
+// should be used for SNI in faketls and MTG verifies it. Also, this is when
36
+// mtg gets about a domain fronting hostname.
38
 //
37
 //
39
-// Secrets can be serialized into 2 forms: hex and base64. If
40
-// you decode both forms into bytes, you'll get the same byte array.
41
-// Telegram clients nowadays accept all forms.
38
+// Secrets can be serialized into 2 forms: hex and base64. If you decode both
39
+// forms into bytes, you'll get the same byte array. Telegram clients nowadays
40
+// accept all forms.
42
 type Secret struct {
41
 type Secret struct {
43
 	// Key is a set of bytes used for traffic authentication.
42
 	// Key is a set of bytes used for traffic authentication.
44
 	Key [SecretKeyLength]byte
43
 	Key [SecretKeyLength]byte

+ 32
- 42
network/init.go View File

1
 // Network contains a default implementation of the network.
1
 // Network contains a default implementation of the network.
2
 //
2
 //
3
-// Please see mtglib.Network interface to get some basic idea behind
4
-// this abstraction.
3
+// Please see [mtglib.Network] interface to get some basic idea behind this
4
+// abstraction.
5
 //
5
 //
6
 // Some notable feature of this implementation:
6
 // Some notable feature of this implementation:
7
 //
7
 //
8
-// 1. It detaches dialer from a network. Dialer is something which
9
-// implements a real dialer and network completes it with more higher
10
-// level details.
11
-//
12
-// 2. It uses only TCP connections. Even for DNS it uses DNS-Over-HTTPS
13
-//
14
-// 3. It has some simple implementation of DNS cache which is good
15
-// enough for our purpose.
16
-//
17
-// 4. It sets uses SO_REUSEPORT port if applicable.
8
+//  1. It detaches dialer from a network. Dialer is something which implements a
9
+//     real dialer and network completes it with more higher level details.
10
+//  2. It uses only TCP connections. Even for DNS it uses DNS-Over-HTTPS
11
+//  3. It has some simple implementation of DNS cache which is good enough for
12
+//     our purpose.
13
+//  4. It sets uses SO_REUSEPORT port if applicable.
18
 package network
14
 package network
19
 
15
 
20
 import (
16
 import (
26
 )
22
 )
27
 
23
 
28
 const (
24
 const (
29
-	// DefaultTimeout is a default timeout for establishing TCP
30
-	// connection.
25
+	// DefaultTimeout is a default timeout for establishing TCP connection.
31
 	DefaultTimeout = 10 * time.Second
26
 	DefaultTimeout = 10 * time.Second
32
 
27
 
33
-	// DefaultHTTPTimeout defines a default timeout for making HTTP
34
-	// request.
28
+	// DefaultHTTPTimeout defines a default timeout for making HTTP request.
35
 	DefaultHTTPTimeout = 10 * time.Second
29
 	DefaultHTTPTimeout = 10 * time.Second
36
 
30
 
37
 	// Deprecated:
31
 	// Deprecated:
38
 	//
32
 	//
39
-	// DefaultBufferSize defines a TCP buffer size. Both read and write, so
40
-	// for real size, please multiply this number by 2.
33
+	// DefaultBufferSize defines a TCP buffer size. Both read and write, so for
34
+	// real size, please multiply this number by 2.
41
 	DefaultBufferSize = 16 * 1024 // 16 kib
35
 	DefaultBufferSize = 16 * 1024 // 16 kib
42
 
36
 
43
-	// DefaultTCPKeepAlivePeriod defines a time period between 2
44
-	// consequitive probes.
37
+	// DefaultTCPKeepAlivePeriod defines a time period between 2 consequitive
38
+	// probes.
45
 	DefaultTCPKeepAlivePeriod = 10 * time.Second
39
 	DefaultTCPKeepAlivePeriod = 10 * time.Second
46
 
40
 
47
-	// ProxyDialerOpenThreshold is used for load balancing SOCKS5 dialer
48
-	// only.
41
+	// ProxyDialerOpenThreshold is used for load balancing SOCKS5 dialer only.
49
 	//
42
 	//
50
-	// This dialer uses circuit breaker with of 3 stages: OPEN,
51
-	// HALF_OPEN and CLOSED. If state is CLOSED, all requests go in
52
-	// a normal mode. If you get more that ProxyDialerOpenThreshold
53
-	// errors, circuit breaker goes into OPEN mode.
43
+	// This dialer uses circuit breaker with of 3 stages: OPEN, HALF_OPEN and
44
+	// CLOSED. If state is CLOSED, all requests go in a normal mode. If you get
45
+	// more that ProxyDialerOpenThreshold errors, circuit breaker goes into OPEN
46
+	// mode.
54
 	//
47
 	//
55
-	// When circuit breaker is in OPEN mode, it forbids all request to
56
-	// a given proxy. But after ProxyDialerHalfOpenTimeout it gives a
57
-	// second chance and opens an access for a SINGLE request. If this
58
-	// request success, then circuit breaker closes, otherwise opens
59
-	// again.
48
+	// When circuit breaker is in OPEN mode, it forbids all request to a given
49
+	// proxy. But after ProxyDialerHalfOpenTimeout it gives a second chance and
50
+	// opens an access for a SINGLE request. If this request success, then circuit
51
+	// breaker closes, otherwise opens again.
60
 	//
52
 	//
61
 	// When circuit breaker is closed, it clears an error states each
53
 	// When circuit breaker is closed, it clears an error states each
62
 	// ProxyDialerResetFailuresTimeout.
54
 	// ProxyDialerResetFailuresTimeout.
63
 	ProxyDialerOpenThreshold = 5
55
 	ProxyDialerOpenThreshold = 5
64
 
56
 
65
-	// ProxyDialerHalfOpenTimeout defines a halfopen timeout for circuit
66
-	// breaker.
57
+	// ProxyDialerHalfOpenTimeout defines a halfopen timeout for circuit breaker.
67
 	ProxyDialerHalfOpenTimeout = time.Minute
58
 	ProxyDialerHalfOpenTimeout = time.Minute
68
 
59
 
69
-	// ProxyDialerResetFailuresTimeout defines a timeout for resetting a
70
-	// failure.
60
+	// ProxyDialerResetFailuresTimeout defines a timeout for resetting a failure.
71
 	ProxyDialerResetFailuresTimeout = 10 * time.Second
61
 	ProxyDialerResetFailuresTimeout = 10 * time.Second
72
 
62
 
73
-	// DefaultDOHHostname defines a default IP address for DOH host.
74
-	// Since mtg is simple, please pass IP address here. We do not
75
-	// have bootstrap servers here embedded.
63
+	// DefaultDOHHostname defines a default IP address for DOH host. Since mtg is
64
+	// simple, please pass IP address here. We do not have bootstrap servers here
65
+	// embedded.
76
 	DefaultDOHHostname = "9.9.9.9"
66
 	DefaultDOHHostname = "9.9.9.9"
77
 
67
 
78
 	// DNSTimeout defines a timeout for DNS queries.
68
 	// DNSTimeout defines a timeout for DNS queries.
84
 )
74
 )
85
 
75
 
86
 var (
76
 var (
87
-	// ErrCircuitBreakerOpened is returned when proxy is being accessed
88
-	// but circuit breaker is opened.
77
+	// ErrCircuitBreakerOpened is returned when proxy is being accessed but
78
+	// circuit breaker is opened.
89
 	ErrCircuitBreakerOpened = errors.New("circuit breaker is opened")
79
 	ErrCircuitBreakerOpened = errors.New("circuit breaker is opened")
90
 
80
 
91
-	// ErrCannotDialWithAllProxies is returned when load balancing
92
-	// client is trying to access proxies but all of them are failed.
81
+	// ErrCannotDialWithAllProxies is returned when load balancing client is
82
+	// trying to access proxies but all of them are failed.
93
 	ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
83
 	ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
94
 )
84
 )
95
 
85
 

+ 6
- 8
network/load_balanced_socks5.go View File

33
 	return nil, ErrCannotDialWithAllProxies
33
 	return nil, ErrCannotDialWithAllProxies
34
 }
34
 }
35
 
35
 
36
-// NewLoadBalancedSocks5Dialer builds a new load balancing SOCKS5
37
-// dialer.
36
+// NewLoadBalancedSocks5Dialer builds a new load balancing SOCKS5 dialer.
38
 //
37
 //
39
-// The main difference from one which is made by NewSocks5Dialer is that
40
-// we actually have a list of these proxies. When dial is requested,
41
-// any proxy is picked and used. If proxy fails for some reason, we try
42
-// another one.
38
+// The main difference from one which is made by NewSocks5Dialer is that we
39
+// actually have a list of these proxies. When dial is requested, any proxy is
40
+// picked and used. If proxy fails for some reason, we try another one.
43
 //
41
 //
44
-// So, it is mostly useful if you have some routes with proxies which
45
-// are not always online or having buggy network.
42
+// So, it is mostly useful if you have some routes with proxies which are not
43
+// always online or having buggy network.
46
 func NewLoadBalancedSocks5Dialer(baseDialer Dialer, proxyURLs []*url.URL) (Dialer, error) {
44
 func NewLoadBalancedSocks5Dialer(baseDialer Dialer, proxyURLs []*url.URL) (Dialer, error) {
47
 	dialers := make([]Dialer, 0, len(proxyURLs))
45
 	dialers := make([]Dialer, 0, len(proxyURLs))
48
 
46
 

+ 2
- 2
network/network.go View File

118
 	return ips, nil
118
 	return ips, nil
119
 }
119
 }
120
 
120
 
121
-// NewNetwork assembles an mtglib.Network compatible structure
122
-// based on a dialer and given params.
121
+// NewNetwork assembles an mtglib.Network compatible structure based on a
122
+// dialer and given params.
123
 //
123
 //
124
 // It brings simple DNS cache and DNS-Over-HTTPS when necessary.
124
 // It brings simple DNS cache and DNS-Over-HTTPS when necessary.
125
 func NewNetwork(dialer Dialer,
125
 func NewNetwork(dialer Dialer,

+ 2
- 2
network/socks5.go View File

136
 	return nil
136
 	return nil
137
 }
137
 }
138
 
138
 
139
-// NewSocks5Dialer build a new dialer from a given one (so, in theory
140
-// you can chain here). Proxy parameters are passed with URI in a form of:
139
+// NewSocks5Dialer build a new dialer from a given one (so, in theory you can
140
+// chain here). Proxy parameters are passed with URI in a form of:
141
 //
141
 //
142
 //     socks5://[user:[password]]@host:port
142
 //     socks5://[user:[password]]@host:port
143
 func NewSocks5Dialer(baseDialer Dialer, proxyURL *url.URL) (Dialer, error) {
143
 func NewSocks5Dialer(baseDialer Dialer, proxyURL *url.URL) (Dialer, error) {

+ 1
- 1
stats/init.go View File

1
-// Stats package has implementations of events.Observers for different
1
+// Stats package has implementations of [events.Observer] for different
2
 // monitoring systems.
2
 // monitoring systems.
3
 //
3
 //
4
 // Observer is a consumer of events produced by mtg. Consumers, defined
4
 // Observer is a consumer of events produced by mtg. Consumers, defined

+ 3
- 4
stats/prometheus.go View File

139
 	}
139
 	}
140
 }
140
 }
141
 
141
 
142
-// PrometheusFactory is a factory of events.Observers which collect
142
+// PrometheusFactory is a factory of [events.Observer] which collect
143
 // information in a format suitable for Prometheus.
143
 // information in a format suitable for Prometheus.
144
 //
144
 //
145
-// This factory can also serve on a given listener. In that case it
146
-// starts HTTP server with a single endpoint - a Prometheus-compatible
147
-// scrape output.
145
+// This factory can also serve on a given listener. In that case it starts HTTP
146
+// server with a single endpoint - a Prometheus-compatible scrape output.
148
 type PrometheusFactory struct {
147
 type PrometheusFactory struct {
149
 	httpServer *http.Server
148
 	httpServer *http.Server
150
 
149
 

+ 7
- 8
stats/statsd.go View File

147
 	}
147
 	}
148
 }
148
 }
149
 
149
 
150
-// StatsdFactory is a factory of events.Observers which dumps
151
-// information to statsd.
150
+// StatsdFactory is a factory of [events.Observer] which dumps information to
151
+// statsd.
152
 //
152
 //
153
-// Please beware that we support ONLY UDP endpoints there. And this
154
-// factory won't use mtglib.Network so it won't use a proxy if you
155
-// provide any. If you need it, I would recommend starting a local
156
-// statsd and route metrics further by features of the chosen server.
153
+// Please beware that we support ONLY UDP endpoints there. And this factory
154
+// won't use [mtglib.Network] so it won't use a proxy if you provide any. If
155
+// you need it, I would recommend starting a local statsd and route metrics
156
+// further by features of the chosen server.
157
 type StatsdFactory struct {
157
 type StatsdFactory struct {
158
 	client *statsd.Client
158
 	client *statsd.Client
159
 }
159
 }
171
 	}
171
 	}
172
 }
172
 }
173
 
173
 
174
-// NewStatsd builds an events.ObserverFactory that sends events
175
-// to statsd.
174
+// NewStatsd builds an [events.ObserverFactory] that sends events to statsd.
176
 //
175
 //
177
 // Valid tagFormats are 'datadog', 'influxdb' and 'graphite'.
176
 // Valid tagFormats are 'datadog', 'influxdb' and 'graphite'.
178
 func NewStatsd(address string, log logger.StdLikeLogger,
177
 func NewStatsd(address string, log logger.StdLikeLogger,

Loading…
Cancel
Save