Browse Source

Fix lint errors

tags/0.9
9seconds 7 years ago
parent
commit
29b5130c95

+ 1
- 1
Gopkg.lock View File

86
 [solve-meta]
86
 [solve-meta]
87
   analyzer-name = "dep"
87
   analyzer-name = "dep"
88
   analyzer-version = 1
88
   analyzer-version = 1
89
-  inputs-digest = "312c9fb15085cbe9660443b15a07981990e1f70ec3ddfcce1b7e6cd5902307da"
89
+  inputs-digest = "c4fdd3664f683342ad0c2509f4a8bcfe5b267a6e8cdaf36f70d39536bbf89834"
90
   solver-name = "gps-cdcl"
90
   solver-name = "gps-cdcl"
91
   solver-version = 1
91
   solver-version = 1

+ 1
- 0
client/client.go View File

8
 	"github.com/9seconds/mtg/wrappers"
8
 	"github.com/9seconds/mtg/wrappers"
9
 )
9
 )
10
 
10
 
11
+// Init defines common method for initializing client connections.
11
 type Init func(net.Conn, string, *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error)
12
 type Init func(net.Conn, string, *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error)

+ 5
- 3
client/direct.go View File

18
 	writeBufferSize  = 64 * 1024
18
 	writeBufferSize  = 64 * 1024
19
 )
19
 )
20
 
20
 
21
+// DirectInit initializes client connection for proxy which connects to
22
+// Telegram directly.
21
 func DirectInit(socket net.Conn, connID string, conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
23
 func DirectInit(socket net.Conn, connID string, conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
22
 	tcpSocket := socket.(*net.TCPConn)
24
 	tcpSocket := socket.(*net.TCPConn)
23
 	if err := tcpSocket.SetNoDelay(false); err != nil {
25
 	if err := tcpSocket.SetNoDelay(false); err != nil {
30
 		return nil, nil, errors.Annotate(err, "Cannot set write buffer size of client socket")
32
 		return nil, nil, errors.Annotate(err, "Cannot set write buffer size of client socket")
31
 	}
33
 	}
32
 
34
 
33
-	socket.SetReadDeadline(time.Now().Add(handshakeTimeout))
35
+	socket.SetReadDeadline(time.Now().Add(handshakeTimeout)) // nolint: errcheck
34
 	frame, err := obfuscated2.ExtractFrame(socket)
36
 	frame, err := obfuscated2.ExtractFrame(socket)
35
 	if err != nil {
37
 	if err != nil {
36
 		return nil, nil, errors.Annotate(err, "Cannot extract frame")
38
 		return nil, nil, errors.Annotate(err, "Cannot extract frame")
37
 	}
39
 	}
38
-	socket.SetReadDeadline(time.Time{})
39
-	conn := wrappers.NewConn(socket, connID, wrappers.ConnPurposeClient, conf.PublicIPv4, conf.PublicIPv6)
40
+	socket.SetReadDeadline(time.Time{}) // nolint: errcheck
40
 
41
 
42
+	conn := wrappers.NewConn(socket, connID, wrappers.ConnPurposeClient, conf.PublicIPv4, conf.PublicIPv6)
41
 	obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame)
43
 	obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame)
42
 	if err != nil {
44
 	if err != nil {
43
 		return nil, nil, errors.Annotate(err, "Cannot parse obfuscated frame")
45
 		return nil, nil, errors.Annotate(err, "Cannot parse obfuscated frame")

+ 2
- 0
client/middle.go View File

8
 	"github.com/9seconds/mtg/wrappers"
8
 	"github.com/9seconds/mtg/wrappers"
9
 )
9
 )
10
 
10
 
11
+// MiddleInit initializes client connection for proxy which has to
12
+// support promoted channels, connect to Telegram middle proxies etc.
11
 func MiddleInit(socket net.Conn, connID string, conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
13
 func MiddleInit(socket net.Conn, connID string, conf *config.Config) (wrappers.Wrap, *mtproto.ConnectionOpts, error) {
12
 	conn, opts, err := DirectInit(socket, connID, conf)
14
 	conn, opts, err := DirectInit(socket, connID, conf)
13
 	if err != nil {
15
 	if err != nil {

+ 2
- 0
config/config.go View File

58
 	return getAddr(c.StatsIP, c.StatsPort)
58
 	return getAddr(c.StatsIP, c.StatsPort)
59
 }
59
 }
60
 
60
 
61
+// UseMiddleProxy defines if this proxy has to connect middle proxies
62
+// which supports promoted channels or directly access Telegram.
61
 func (c *Config) UseMiddleProxy() bool {
63
 func (c *Config) UseMiddleProxy() bool {
62
 	return len(c.AdTag) > 0
64
 	return len(c.AdTag) > 0
63
 }
65
 }

+ 1
- 1
main.go View File

114
 		atom,
114
 		atom,
115
 	))
115
 	))
116
 	zap.ReplaceGlobals(logger)
116
 	zap.ReplaceGlobals(logger)
117
-	defer logger.Sync()
117
+	defer logger.Sync() // nolint: errcheck
118
 
118
 
119
 	printURLs(conf.GetURLs())
119
 	printURLs(conf.GetURLs())
120
 
120
 

+ 10
- 3
mtproto/connection_options.go View File

11
 // by the user.
11
 // by the user.
12
 type ConnectionType uint8
12
 type ConnectionType uint8
13
 
13
 
14
+// ConnectionProtocol is a type of IP protocol to use.
14
 type ConnectionProtocol uint8
15
 type ConnectionProtocol uint8
15
 
16
 
17
+// Hacks is a simple structure to store flags for packet transmission.
16
 type Hacks struct {
18
 type Hacks struct {
17
 	SimpleAck bool
19
 	SimpleAck bool
18
 	QuickAck  bool
20
 	QuickAck  bool
24
 	DC              int16
26
 	DC              int16
25
 	ConnectionType  ConnectionType
27
 	ConnectionType  ConnectionType
26
 	ConnectionProto ConnectionProtocol
28
 	ConnectionProto ConnectionProtocol
27
-	ReadHacks       Hacks
28
-	WriteHacks      Hacks
29
-	ClientAddr      *net.TCPAddr
29
+	// Read and Write means direction related to the client.
30
+	// ReadHacks are meant to be flushed on client read
31
+	// WriteHacks are meant to be flushed on client write.
32
+	ReadHacks  Hacks
33
+	WriteHacks Hacks
34
+	ClientAddr *net.TCPAddr
30
 }
35
 }
31
 
36
 
32
 // Different connection types which user requests from Telegram.
37
 // Different connection types which user requests from Telegram.
36
 	ConnectionTypeIntermediate
41
 	ConnectionTypeIntermediate
37
 )
42
 )
38
 
43
 
44
+// ConnectionProtocol* define which connection protocols to use.
45
+// ConnectionProtocolAny means that any is suitable.
39
 const (
46
 const (
40
 	ConnectionProtocolIPv4 ConnectionProtocol = 1
47
 	ConnectionProtocolIPv4 ConnectionProtocol = 1
41
 	ConnectionProtocolIPv6                    = ConnectionProtocolIPv4 << 1
48
 	ConnectionProtocolIPv6                    = ConnectionProtocolIPv4 << 1

+ 4
- 0
mtproto/rpc/handshake_request.go View File

2
 
2
 
3
 import "bytes"
3
 import "bytes"
4
 
4
 
5
+// HandshakeRequest is the data type which is responsible for
6
+// constructing of correct handshake request.
5
 type HandshakeRequest struct {
7
 type HandshakeRequest struct {
6
 }
8
 }
7
 
9
 
10
+// Bytes returns serialized handshake request.
8
 func (r *HandshakeRequest) Bytes() []byte {
11
 func (r *HandshakeRequest) Bytes() []byte {
9
 	buf := &bytes.Buffer{}
12
 	buf := &bytes.Buffer{}
10
 	buf.Grow(len(TagHandshake) + len(HandshakeFlags) + len(HandshakeSenderPID) + len(HandshakePeerPID))
13
 	buf.Grow(len(TagHandshake) + len(HandshakeFlags) + len(HandshakeSenderPID) + len(HandshakePeerPID))
17
 	return buf.Bytes()
20
 	return buf.Bytes()
18
 }
21
 }
19
 
22
 
23
+// NewHandshakeRequest creates new HandshakeRequest instance.
20
 func NewHandshakeRequest() *HandshakeRequest {
24
 func NewHandshakeRequest() *HandshakeRequest {
21
 	return &HandshakeRequest{}
25
 	return &HandshakeRequest{}
22
 }
26
 }

+ 6
- 0
mtproto/rpc/handshake_response.go View File

6
 	"github.com/juju/errors"
6
 	"github.com/juju/errors"
7
 )
7
 )
8
 
8
 
9
+// HandshakeResponse defines data structure which is used for storage of
10
+// handshake response.
9
 type HandshakeResponse struct {
11
 type HandshakeResponse struct {
10
 	Type      []byte
12
 	Type      []byte
11
 	Flags     []byte
13
 	Flags     []byte
13
 	PeerPID   []byte
15
 	PeerPID   []byte
14
 }
16
 }
15
 
17
 
18
+// Bytes returns a serialized handshake response.
16
 func (r *HandshakeResponse) Bytes() []byte {
19
 func (r *HandshakeResponse) Bytes() []byte {
17
 	buf := &bytes.Buffer{}
20
 	buf := &bytes.Buffer{}
18
 
21
 
24
 	return buf.Bytes()
27
 	return buf.Bytes()
25
 }
28
 }
26
 
29
 
30
+// Valid checks that handshake response compliments request.
27
 func (r *HandshakeResponse) Valid(req *HandshakeRequest) error {
31
 func (r *HandshakeResponse) Valid(req *HandshakeRequest) error {
28
 	if !bytes.Equal(r.Type, TagHandshake) {
32
 	if !bytes.Equal(r.Type, TagHandshake) {
29
 		return errors.New("Unexpected handshake tag")
33
 		return errors.New("Unexpected handshake tag")
35
 	return nil
39
 	return nil
36
 }
40
 }
37
 
41
 
42
+// NewHandshakeResponse constructs new handshake response from the given
43
+// data.
38
 func NewHandshakeResponse(data []byte) (*HandshakeResponse, error) {
44
 func NewHandshakeResponse(data []byte) (*HandshakeResponse, error) {
39
 	if len(data) != 32 {
45
 	if len(data) != 32 {
40
 		return nil, errors.New("Incorrect handshake response length")
46
 		return nil, errors.New("Incorrect handshake response length")

+ 4
- 0
mtproto/rpc/nonce_request.go View File

9
 	"github.com/juju/errors"
9
 	"github.com/juju/errors"
10
 )
10
 )
11
 
11
 
12
+// NonceRequest is the data type which contains all the data for correct
13
+// nonce request.
12
 type NonceRequest struct {
14
 type NonceRequest struct {
13
 	KeySelector []byte
15
 	KeySelector []byte
14
 	CryptoTS    []byte
16
 	CryptoTS    []byte
15
 	Nonce       []byte
17
 	Nonce       []byte
16
 }
18
 }
17
 
19
 
20
+// Bytes returns serialized nonce request.
18
 func (r *NonceRequest) Bytes() []byte {
21
 func (r *NonceRequest) Bytes() []byte {
19
 	buf := &bytes.Buffer{}
22
 	buf := &bytes.Buffer{}
20
 
23
 
27
 	return buf.Bytes()
30
 	return buf.Bytes()
28
 }
31
 }
29
 
32
 
33
+// NewNonceRequest builds new none request based on proxy secret.
30
 func NewNonceRequest(proxySecret []byte) (*NonceRequest, error) {
34
 func NewNonceRequest(proxySecret []byte) (*NonceRequest, error) {
31
 	nonce := make([]byte, 16)
35
 	nonce := make([]byte, 16)
32
 	keySelector := make([]byte, 4)
36
 	keySelector := make([]byte, 4)

+ 4
- 0
mtproto/rpc/nonce_response.go View File

6
 	"github.com/juju/errors"
6
 	"github.com/juju/errors"
7
 )
7
 )
8
 
8
 
9
+// NonceResponse is the data type which contains data of nonce response.
9
 type NonceResponse struct {
10
 type NonceResponse struct {
10
 	NonceRequest
11
 	NonceRequest
11
 
12
 
13
 	Crypto []byte
14
 	Crypto []byte
14
 }
15
 }
15
 
16
 
17
+// Bytes returns serialized form of the nonce response.
16
 func (r *NonceResponse) Bytes() []byte {
18
 func (r *NonceResponse) Bytes() []byte {
17
 	buf := &bytes.Buffer{}
19
 	buf := &bytes.Buffer{}
18
 
20
 
25
 	return buf.Bytes()
27
 	return buf.Bytes()
26
 }
28
 }
27
 
29
 
30
+// Valid checks that nonce response compliments nonce request.
28
 func (r *NonceResponse) Valid(req *NonceRequest) error {
31
 func (r *NonceResponse) Valid(req *NonceRequest) error {
29
 	if !bytes.Equal(r.Type, TagNonce) {
32
 	if !bytes.Equal(r.Type, TagNonce) {
30
 		return errors.New("Unexpected RPC type")
33
 		return errors.New("Unexpected RPC type")
39
 	return nil
42
 	return nil
40
 }
43
 }
41
 
44
 
45
+// NewNonceResponse build new nonce response based on the given data.
42
 func NewNonceResponse(data []byte) (*NonceResponse, error) {
46
 func NewNonceResponse(data []byte) (*NonceResponse, error) {
43
 	if len(data) != 32 {
47
 	if len(data) != 32 {
44
 		return nil, errors.New("Unexpected message length")
48
 		return nil, errors.New("Unexpected message length")

+ 5
- 0
mtproto/rpc/proxy_request.go View File

12
 	"github.com/9seconds/mtg/mtproto"
12
 	"github.com/9seconds/mtg/mtproto"
13
 )
13
 )
14
 
14
 
15
+// ProxyRequest is the data type for storing data required to compose
16
+// RPC_PROXY_REQ request.
15
 type ProxyRequest struct {
17
 type ProxyRequest struct {
16
 	Flags        proxyRequestFlags
18
 	Flags        proxyRequestFlags
17
 	ConnectionID []byte
19
 	ConnectionID []byte
21
 	Options      *mtproto.ConnectionOpts
23
 	Options      *mtproto.ConnectionOpts
22
 }
24
 }
23
 
25
 
26
+// MakeHeader makes RPC_PROXY_REQ header. We need only to append the
27
+// data for it.
24
 func (r *ProxyRequest) MakeHeader(message []byte) (*bytes.Buffer, fmt.Stringer) {
28
 func (r *ProxyRequest) MakeHeader(message []byte) (*bytes.Buffer, fmt.Stringer) {
25
 	bufferLength := len(TagProxyRequest) +
29
 	bufferLength := len(TagProxyRequest) +
26
 		4 + // len(flags)
30
 		4 + // len(flags)
59
 	return buf, flags
63
 	return buf, flags
60
 }
64
 }
61
 
65
 
66
+// NewProxyRequest build new ProxyRequest data structure.
62
 func NewProxyRequest(clientAddr, ownAddr *net.TCPAddr, opts *mtproto.ConnectionOpts, adTag []byte) (*ProxyRequest, error) {
67
 func NewProxyRequest(clientAddr, ownAddr *net.TCPAddr, opts *mtproto.ConnectionOpts, adTag []byte) (*ProxyRequest, error) {
63
 	flags := proxyRequestFlagsHasAdTag | proxyRequestFlagsMagic | proxyRequestFlagsExtMode2
68
 	flags := proxyRequestFlagsHasAdTag | proxyRequestFlagsMagic | proxyRequestFlagsExtMode2
64
 
69
 

+ 3
- 0
mtproto/rpc/rpc.go View File

1
 package rpc
1
 package rpc
2
 
2
 
3
+// SeqNo* is the number of the sequence which have special meaning for
4
+// the Telegram.
3
 const (
5
 const (
4
 	SeqNoNonce     = -2
6
 	SeqNoNonce     = -2
5
 	SeqNoHandshake = -1
7
 	SeqNoHandshake = -1
6
 )
8
 )
7
 
9
 
10
+// Different constants for RPC protocol
8
 var (
11
 var (
9
 	TagCloseExt     = []byte{0xa2, 0x34, 0xb6, 0x5e}
12
 	TagCloseExt     = []byte{0xa2, 0x34, 0xb6, 0x5e}
10
 	TagProxyAns     = []byte{0x0d, 0xda, 0x03, 0x44}
13
 	TagProxyAns     = []byte{0x0d, 0xda, 0x03, 0x44}

+ 12
- 9
proxy/proxy.go View File

17
 	"github.com/9seconds/mtg/wrappers"
17
 	"github.com/9seconds/mtg/wrappers"
18
 )
18
 )
19
 
19
 
20
+// Proxy is a core of this program.
20
 type Proxy struct {
21
 type Proxy struct {
21
 	clientInit client.Init
22
 	clientInit client.Init
22
 	tg         telegram.Telegram
23
 	tg         telegram.Telegram
23
 	conf       *config.Config
24
 	conf       *config.Config
24
 }
25
 }
25
 
26
 
27
+// Serve runs TCP proxy server.
26
 func (p *Proxy) Serve() error {
28
 func (p *Proxy) Serve() error {
27
 	lsock, err := net.Listen("tcp", p.conf.BindAddr())
29
 	lsock, err := net.Listen("tcp", p.conf.BindAddr())
28
 	if err != nil {
30
 	if err != nil {
43
 	log := zap.S().With("connection_id", connID).Named("main")
45
 	log := zap.S().With("connection_id", connID).Named("main")
44
 
46
 
45
 	defer func() {
47
 	defer func() {
46
-		conn.Close()
48
+		conn.Close() // nolint: errcheck
47
 
49
 
48
 		if err := recover(); err != nil {
50
 		if err := recover(); err != nil {
49
 			stats.NewCrash()
51
 			stats.NewCrash()
58
 		log.Errorw("Cannot initialize client connection", "error", err)
60
 		log.Errorw("Cannot initialize client connection", "error", err)
59
 		return
61
 		return
60
 	}
62
 	}
61
-	defer client.(io.Closer).Close()
63
+	defer client.(io.Closer).Close() // nolint: errcheck
62
 
64
 
63
 	stats.ClientConnected(opts.ConnectionType, client.RemoteAddr())
65
 	stats.ClientConnected(opts.ConnectionType, client.RemoteAddr())
64
 	defer stats.ClientDisconnected(opts.ConnectionType, client.RemoteAddr())
66
 	defer stats.ClientDisconnected(opts.ConnectionType, client.RemoteAddr())
68
 		log.Errorw("Cannot initialize server connection", "error", err)
70
 		log.Errorw("Cannot initialize server connection", "error", err)
69
 		return
71
 		return
70
 	}
72
 	}
71
-	defer server.(io.Closer).Close()
73
+	defer server.(io.Closer).Close() // nolint: errcheck
72
 
74
 
73
 	wait := &sync.WaitGroup{}
75
 	wait := &sync.WaitGroup{}
74
 	wait.Add(2)
76
 	wait.Add(2)
104
 	return packetConn, nil
106
 	return packetConn, nil
105
 }
107
 }
106
 
108
 
107
-func (p *Proxy) middlePipe(src wrappers.PacketReadCloser, dst wrappers.PacketWriteCloser, wait *sync.WaitGroup, hacks *mtproto.Hacks) {
109
+func (p *Proxy) middlePipe(src wrappers.PacketReadCloser, dst io.WriteCloser, wait *sync.WaitGroup, hacks *mtproto.Hacks) {
108
 	defer func() {
110
 	defer func() {
109
-		src.Close()
110
-		dst.Close()
111
+		src.Close() // nolint: errcheck
112
+		dst.Close() // nolint: errcheck
111
 		wait.Done()
113
 		wait.Done()
112
 	}()
114
 	}()
113
 
115
 
127
 	}
129
 	}
128
 }
130
 }
129
 
131
 
130
-func (p *Proxy) directPipe(src wrappers.StreamReadCloser, dst wrappers.StreamWriteCloser, wait *sync.WaitGroup) {
132
+func (p *Proxy) directPipe(src wrappers.StreamReadCloser, dst io.WriteCloser, wait *sync.WaitGroup) {
131
 	defer func() {
133
 	defer func() {
132
-		src.Close()
133
-		dst.Close()
134
+		src.Close() // nolint: errcheck
135
+		dst.Close() // nolint: errcheck
134
 		wait.Done()
136
 		wait.Done()
135
 	}()
137
 	}()
136
 
138
 
139
 	}
141
 	}
140
 }
142
 }
141
 
143
 
144
+// NewProxy returns new proxy instance.
142
 func NewProxy(conf *config.Config) *Proxy {
145
 func NewProxy(conf *config.Config) *Proxy {
143
 	var clientInit client.Init
146
 	var clientInit client.Init
144
 	var tg telegram.Telegram
147
 	var tg telegram.Telegram

+ 7
- 2
stats/channels.go View File

21
 
21
 
22
 type connectionData struct {
22
 type connectionData struct {
23
 	connectionType mtproto.ConnectionType
23
 	connectionType mtproto.ConnectionType
24
-	addr           *net.TCPAddr
25
 	connected      bool
24
 	connected      bool
25
+	addr           *net.TCPAddr
26
 }
26
 }
27
 
27
 
28
 type trafficData struct {
28
 type trafficData struct {
40
 	}
40
 	}
41
 }
41
 }
42
 
42
 
43
-func connectionManager() {
43
+func connectionManager() { // nolint: gocyclo
44
 	for event := range connectionsChan {
44
 	for event := range connectionsChan {
45
 		instance.mutex.RLock()
45
 		instance.mutex.RLock()
46
 
46
 
111
 	}
111
 	}
112
 }
112
 }
113
 
113
 
114
+// NewCrash indicates new crash.
114
 func NewCrash() {
115
 func NewCrash() {
115
 	crashesChan <- struct{}{}
116
 	crashesChan <- struct{}{}
116
 }
117
 }
117
 
118
 
119
+// ClientConnected indicates that new client was connected.
118
 func ClientConnected(connectionType mtproto.ConnectionType, addr *net.TCPAddr) {
120
 func ClientConnected(connectionType mtproto.ConnectionType, addr *net.TCPAddr) {
119
 	connectionsChan <- &connectionData{
121
 	connectionsChan <- &connectionData{
120
 		connectionType: connectionType,
122
 		connectionType: connectionType,
123
 	}
125
 	}
124
 }
126
 }
125
 
127
 
128
+// ClientDisconnected indicates that client was disconnected.
126
 func ClientDisconnected(connectionType mtproto.ConnectionType, addr *net.TCPAddr) {
129
 func ClientDisconnected(connectionType mtproto.ConnectionType, addr *net.TCPAddr) {
127
 	connectionsChan <- &connectionData{
130
 	connectionsChan <- &connectionData{
128
 		connectionType: connectionType,
131
 		connectionType: connectionType,
131
 	}
134
 	}
132
 }
135
 }
133
 
136
 
137
+// IngressTraffic accounts new ingress traffic.
134
 func IngressTraffic(traffic int) {
138
 func IngressTraffic(traffic int) {
135
 	trafficChan <- &trafficData{
139
 	trafficChan <- &trafficData{
136
 		traffic: traffic,
140
 		traffic: traffic,
138
 	}
142
 	}
139
 }
143
 }
140
 
144
 
145
+// EgressTraffic accounts new ingress traffic.
141
 func EgressTraffic(traffic int) {
146
 func EgressTraffic(traffic int) {
142
 	trafficChan <- &trafficData{
147
 	trafficChan <- &trafficData{
143
 		traffic: traffic,
148
 		traffic: traffic,

+ 2
- 1
stats/server.go View File

13
 
13
 
14
 var instance *stats
14
 var instance *stats
15
 
15
 
16
+// Start starts new statisitcs server.
16
 func Start(conf *config.Config) {
17
 func Start(conf *config.Config) {
17
 	log := zap.S().Named("stats")
18
 	log := zap.S().Named("stats")
18
 
19
 
40
 		}
41
 		}
41
 
42
 
42
 		interm := map[string]interface{}{}
43
 		interm := map[string]interface{}{}
43
-		json.Unmarshal(first, &interm)
44
+		json.Unmarshal(first, &interm) // nolint: errcheck
44
 
45
 
45
 		encoder := json.NewEncoder(w)
46
 		encoder := json.NewEncoder(w)
46
 		encoder.SetEscapeHTML(false)
47
 		encoder.SetEscapeHTML(false)

+ 4
- 4
telegram/direct.go View File

28
 	}
28
 	}
29
 )
29
 )
30
 
30
 
31
-type DirectTelegram struct {
31
+type directTelegram struct {
32
 	baseTelegram
32
 	baseTelegram
33
 }
33
 }
34
 
34
 
35
-func (t *DirectTelegram) Dial(connID string, connOpts *mtproto.ConnectionOpts) (wrappers.StreamReadWriteCloser, error) {
35
+func (t *directTelegram) Dial(connID string, connOpts *mtproto.ConnectionOpts) (wrappers.StreamReadWriteCloser, error) {
36
 	dc := connOpts.DC
36
 	dc := connOpts.DC
37
 	if dc < 0 {
37
 	if dc < 0 {
38
 		dc = -dc
38
 		dc = -dc
43
 	return t.baseTelegram.dial(dc-1, connID, connOpts.ConnectionProto)
43
 	return t.baseTelegram.dial(dc-1, connID, connOpts.ConnectionProto)
44
 }
44
 }
45
 
45
 
46
-func (t *DirectTelegram) Init(connOpts *mtproto.ConnectionOpts, conn wrappers.StreamReadWriteCloser) (wrappers.Wrap, error) {
46
+func (t *directTelegram) Init(connOpts *mtproto.ConnectionOpts, conn wrappers.StreamReadWriteCloser) (wrappers.Wrap, error) {
47
 	obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame(connOpts)
47
 	obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame(connOpts)
48
 
48
 
49
 	if _, err := conn.Write(frame); err != nil {
49
 	if _, err := conn.Write(frame); err != nil {
56
 // NewDirectTelegram returns Telegram instance which connects directly
56
 // NewDirectTelegram returns Telegram instance which connects directly
57
 // to Telegram bypassing middleproxies.
57
 // to Telegram bypassing middleproxies.
58
 func NewDirectTelegram(conf *config.Config) Telegram {
58
 func NewDirectTelegram(conf *config.Config) Telegram {
59
-	return &DirectTelegram{baseTelegram{
59
+	return &directTelegram{baseTelegram{
60
 		dialer: tgDialer{
60
 		dialer: tgDialer{
61
 			Dialer: net.Dialer{Timeout: telegramDialTimeout},
61
 			Dialer: net.Dialer{Timeout: telegramDialTimeout},
62
 			conf:   conf,
62
 			conf:   conf,

+ 10
- 7
telegram/middle.go View File

1
 package telegram
1
 package telegram
2
 
2
 
3
 import (
3
 import (
4
+	"io"
4
 	"net"
5
 	"net"
5
 	"net/http"
6
 	"net/http"
6
 	"sync"
7
 	"sync"
13
 	"github.com/9seconds/mtg/wrappers"
14
 	"github.com/9seconds/mtg/wrappers"
14
 )
15
 )
15
 
16
 
16
-type MiddleTelegram struct {
17
+type middleTelegram struct {
17
 	middleTelegramCaller
18
 	middleTelegramCaller
18
 
19
 
19
 	conf *config.Config
20
 	conf *config.Config
20
 }
21
 }
21
 
22
 
22
-func (t *MiddleTelegram) Init(connOpts *mtproto.ConnectionOpts, conn wrappers.StreamReadWriteCloser) (wrappers.Wrap, error) {
23
+func (t *middleTelegram) Init(connOpts *mtproto.ConnectionOpts, conn wrappers.StreamReadWriteCloser) (wrappers.Wrap, error) {
23
 	rpcNonceConn := wrappers.NewMTProtoFrame(conn, rpc.SeqNoNonce)
24
 	rpcNonceConn := wrappers.NewMTProtoFrame(conn, rpc.SeqNoNonce)
24
 
25
 
25
 	rpcNonceReq, err := t.sendRPCNonceRequest(rpcNonceConn)
26
 	rpcNonceReq, err := t.sendRPCNonceRequest(rpcNonceConn)
52
 	return proxyConn, nil
53
 	return proxyConn, nil
53
 }
54
 }
54
 
55
 
55
-func (t *MiddleTelegram) sendRPCNonceRequest(conn wrappers.PacketWriter) (*rpc.NonceRequest, error) {
56
+func (t *middleTelegram) sendRPCNonceRequest(conn io.Writer) (*rpc.NonceRequest, error) {
56
 	rpcNonceReq, err := rpc.NewNonceRequest(t.proxySecret)
57
 	rpcNonceReq, err := rpc.NewNonceRequest(t.proxySecret)
57
 	if err != nil {
58
 	if err != nil {
58
 		return nil, errors.Annotate(err, "Cannot create RPC nonce request")
59
 		return nil, errors.Annotate(err, "Cannot create RPC nonce request")
64
 	return rpcNonceReq, nil
65
 	return rpcNonceReq, nil
65
 }
66
 }
66
 
67
 
67
-func (t *MiddleTelegram) receiveRPCNonceResponse(conn wrappers.PacketReader, req *rpc.NonceRequest) (*rpc.NonceResponse, error) {
68
+func (t *middleTelegram) receiveRPCNonceResponse(conn wrappers.PacketReader, req *rpc.NonceRequest) (*rpc.NonceResponse, error) {
68
 	packet, err := conn.Read()
69
 	packet, err := conn.Read()
69
 	if err != nil {
70
 	if err != nil {
70
 		return nil, errors.Annotate(err, "Cannot read RPC nonce response")
71
 		return nil, errors.Annotate(err, "Cannot read RPC nonce response")
81
 	return rpcNonceResp, nil
82
 	return rpcNonceResp, nil
82
 }
83
 }
83
 
84
 
84
-func (t *MiddleTelegram) sendRPCHandshakeRequest(conn wrappers.PacketWriter) (*rpc.HandshakeRequest, error) {
85
+func (t *middleTelegram) sendRPCHandshakeRequest(conn io.Writer) (*rpc.HandshakeRequest, error) {
85
 	req := rpc.NewHandshakeRequest()
86
 	req := rpc.NewHandshakeRequest()
86
 	if _, err := conn.Write(req.Bytes()); err != nil {
87
 	if _, err := conn.Write(req.Bytes()); err != nil {
87
 		return nil, errors.Annotate(err, "Cannot send RPC handshake request")
88
 		return nil, errors.Annotate(err, "Cannot send RPC handshake request")
90
 	return req, nil
91
 	return req, nil
91
 }
92
 }
92
 
93
 
93
-func (t *MiddleTelegram) receiveRPCHandshakeResponse(conn wrappers.PacketReader, req *rpc.HandshakeRequest) (*rpc.HandshakeResponse, error) {
94
+func (t *middleTelegram) receiveRPCHandshakeResponse(conn wrappers.PacketReader, req *rpc.HandshakeRequest) (*rpc.HandshakeResponse, error) {
94
 	packet, err := conn.Read()
95
 	packet, err := conn.Read()
95
 	if err != nil {
96
 	if err != nil {
96
 		return nil, errors.Annotate(err, "Cannot read RPC handshake response")
97
 		return nil, errors.Annotate(err, "Cannot read RPC handshake response")
107
 	return rpcHandshakeResp, nil
108
 	return rpcHandshakeResp, nil
108
 }
109
 }
109
 
110
 
111
+// NewMiddleTelegram creates new instance of Telegram which works with
112
+// middle proxies.
110
 func NewMiddleTelegram(conf *config.Config) Telegram {
113
 func NewMiddleTelegram(conf *config.Config) Telegram {
111
-	tg := &MiddleTelegram{
114
+	tg := &middleTelegram{
112
 		middleTelegramCaller: middleTelegramCaller{
115
 		middleTelegramCaller: middleTelegramCaller{
113
 			baseTelegram: baseTelegram{
116
 			baseTelegram: baseTelegram{
114
 				dialer: tgDialer{
117
 				dialer: tgDialer{

+ 1
- 1
telegram/middle_caller.go View File

104
 	if err != nil {
104
 	if err != nil {
105
 		return nil, errors.Annotate(err, "Cannot access telegram server")
105
 		return nil, errors.Annotate(err, "Cannot access telegram server")
106
 	}
106
 	}
107
-	defer resp.Body.Close()
107
+	defer resp.Body.Close() // nolint: errcheck
108
 
108
 
109
 	scanner := bufio.NewScanner(resp.Body)
109
 	scanner := bufio.NewScanner(resp.Body)
110
 	data := map[int16][]string{}
110
 	data := map[int16][]string{}

+ 1
- 0
telegram/telegram.go View File

9
 	"github.com/9seconds/mtg/wrappers"
9
 	"github.com/9seconds/mtg/wrappers"
10
 )
10
 )
11
 
11
 
12
+// Telegram is an interface for different Telegram work modes.
12
 type Telegram interface {
13
 type Telegram interface {
13
 	Dial(string, *mtproto.ConnectionOpts) (wrappers.StreamReadWriteCloser, error)
14
 	Dial(string, *mtproto.ConnectionOpts) (wrappers.StreamReadWriteCloser, error)
14
 	Init(*mtproto.ConnectionOpts, wrappers.StreamReadWriteCloser) (wrappers.Wrap, error)
15
 	Init(*mtproto.ConnectionOpts, wrappers.StreamReadWriteCloser) (wrappers.Wrap, error)

+ 1
- 0
utils/read_current_data.go View File

4
 
4
 
5
 const readCurrentDataBufferSize = 1024 + 1 // + 1 because telegram operates with blocks mod 4
5
 const readCurrentDataBufferSize = 1024 + 1 // + 1 because telegram operates with blocks mod 4
6
 
6
 
7
+// ReadCurrentData reads all data from io.Reader which is ready to be read.
7
 func ReadCurrentData(src io.Reader) (rv []byte, err error) {
8
 func ReadCurrentData(src io.Reader) (rv []byte, err error) {
8
 	buf := make([]byte, readCurrentDataBufferSize)
9
 	buf := make([]byte, readCurrentDataBufferSize)
9
 	n := readCurrentDataBufferSize
10
 	n := readCurrentDataBufferSize

+ 1
- 0
utils/reverse_bytes.go View File

1
 package utils
1
 package utils
2
 
2
 
3
+// ReverseBytes is a common slice reverser.
3
 func ReverseBytes(data []byte) []byte {
4
 func ReverseBytes(data []byte) []byte {
4
 	dataLen := len(data)
5
 	dataLen := len(data)
5
 	rv := make([]byte, dataLen)
6
 	rv := make([]byte, dataLen)

+ 4
- 0
utils/uint24.go View File

1
 package utils
1
 package utils
2
 
2
 
3
+// Uint24 is a replacement for the absent Go uint24 data type.
4
+// This data type is little endian.
3
 type Uint24 [3]byte
5
 type Uint24 [3]byte
4
 
6
 
7
+// ToUint24 converts number to Uint24.
5
 func ToUint24(number uint32) Uint24 {
8
 func ToUint24(number uint32) Uint24 {
6
 	return Uint24{byte(number), byte(number >> 8), byte(number >> 16)}
9
 	return Uint24{byte(number), byte(number >> 8), byte(number >> 16)}
7
 }
10
 }
8
 
11
 
12
+// FromUint24 converts Uint24 to number.
9
 func FromUint24(number Uint24) uint32 {
13
 func FromUint24(number Uint24) uint32 {
10
 	return uint32(number[0]) + (uint32(number[1]) << 8) + (uint32(number[2]) << 16)
14
 	return uint32(number[0]) + (uint32(number[1]) << 8) + (uint32(number[2]) << 16)
11
 }
15
 }

+ 9
- 0
wrappers/blockcipher.go View File

12
 	"github.com/juju/errors"
12
 	"github.com/juju/errors"
13
 )
13
 )
14
 
14
 
15
+// BlockCipher is a stream writer which encrypts/decrypts blocks of data
16
+// with AES CBC. This also is buffered reader. It means, that block
17
+// reading is transparent for it, you can assume you are working with
18
+// good old io.Reader.
15
 type BlockCipher struct {
19
 type BlockCipher struct {
16
 	buf *bytes.Buffer
20
 	buf *bytes.Buffer
17
 
21
 
63
 	return b.conn.Write(encrypted)
67
 	return b.conn.Write(encrypted)
64
 }
68
 }
65
 
69
 
70
+// Logger returns an instance of the logger for this wrapper.
66
 func (b *BlockCipher) Logger() *zap.SugaredLogger {
71
 func (b *BlockCipher) Logger() *zap.SugaredLogger {
67
 	return b.logger
72
 	return b.logger
68
 }
73
 }
69
 
74
 
75
+// LocalAddr returns local address of the underlying net.Conn.
70
 func (b *BlockCipher) LocalAddr() *net.TCPAddr {
76
 func (b *BlockCipher) LocalAddr() *net.TCPAddr {
71
 	return b.conn.LocalAddr()
77
 	return b.conn.LocalAddr()
72
 }
78
 }
73
 
79
 
80
+// RemoteAddr returns remote address of the underlying net.Conn.
74
 func (b *BlockCipher) RemoteAddr() *net.TCPAddr {
81
 func (b *BlockCipher) RemoteAddr() *net.TCPAddr {
75
 	return b.conn.RemoteAddr()
82
 	return b.conn.RemoteAddr()
76
 }
83
 }
77
 
84
 
85
+// Close closes underlying net.Conn.
78
 func (b *BlockCipher) Close() error {
86
 func (b *BlockCipher) Close() error {
79
 	return b.conn.Close()
87
 	return b.conn.Close()
80
 }
88
 }
81
 
89
 
90
+// NewBlockCipher creates new instance of BlockCipher based on given data.
82
 func NewBlockCipher(conn StreamReadWriteCloser, encryptor, decryptor cipher.BlockMode) StreamReadWriteCloser {
91
 func NewBlockCipher(conn StreamReadWriteCloser, encryptor, decryptor cipher.BlockMode) StreamReadWriteCloser {
83
 	return &BlockCipher{
92
 	return &BlockCipher{
84
 		buf:       &bytes.Buffer{},
93
 		buf:       &bytes.Buffer{},

+ 18
- 7
wrappers/conn.go View File

9
 	"github.com/9seconds/mtg/stats"
9
 	"github.com/9seconds/mtg/stats"
10
 )
10
 )
11
 
11
 
12
+// ConnPurpose is intented to be identifier of connection purpose. We
13
+// sometimes want to treat client/telegram connection differently (for
14
+// logging for example).
12
 type ConnPurpose uint8
15
 type ConnPurpose uint8
13
 
16
 
14
 func (c ConnPurpose) String() string {
17
 func (c ConnPurpose) String() string {
22
 	return ""
25
 	return ""
23
 }
26
 }
24
 
27
 
28
+// ConnPurpose* define different connection types.
25
 const (
29
 const (
26
 	ConnPurposeClient = iota
30
 	ConnPurposeClient = iota
27
 	ConnPurposeTelegram
31
 	ConnPurposeTelegram
32
 	connTimeoutWrite = 5 * time.Minute
36
 	connTimeoutWrite = 5 * time.Minute
33
 )
37
 )
34
 
38
 
39
+// Conn is a basic wrapper for net.Conn providing the most low-level
40
+// logic and management as possible.
35
 type Conn struct {
41
 type Conn struct {
36
 	connID string
42
 	connID string
37
 	conn   net.Conn
43
 	conn   net.Conn
42
 }
48
 }
43
 
49
 
44
 func (c *Conn) Write(p []byte) (int, error) {
50
 func (c *Conn) Write(p []byte) (int, error) {
45
-	c.conn.SetWriteDeadline(time.Now().Add(connTimeoutWrite))
51
+	c.conn.SetWriteDeadline(time.Now().Add(connTimeoutWrite)) // nolint: errcheck
46
 	n, err := c.conn.Write(p)
52
 	n, err := c.conn.Write(p)
47
 
53
 
48
 	c.logger.Debugw("Write to stream", "bytes", n, "error", err)
54
 	c.logger.Debugw("Write to stream", "bytes", n, "error", err)
52
 }
58
 }
53
 
59
 
54
 func (c *Conn) Read(p []byte) (int, error) {
60
 func (c *Conn) Read(p []byte) (int, error) {
55
-	c.conn.SetReadDeadline(time.Now().Add(connTimeoutRead))
61
+	c.conn.SetReadDeadline(time.Now().Add(connTimeoutRead)) // nolint: errcheck
56
 	n, err := c.conn.Read(p)
62
 	n, err := c.conn.Read(p)
57
 
63
 
58
 	c.logger.Debugw("Read from stream", "bytes", n, "error", err)
64
 	c.logger.Debugw("Read from stream", "bytes", n, "error", err)
61
 	return n, err
67
 	return n, err
62
 }
68
 }
63
 
69
 
70
+// Close closes underlying net.Conn instance.
64
 func (c *Conn) Close() error {
71
 func (c *Conn) Close() error {
65
-	defer c.logger.Debugw("Closed connection")
72
+	defer c.logger.Debugw("Close connection")
66
 	return c.conn.Close()
73
 	return c.conn.Close()
67
 }
74
 }
68
 
75
 
76
+// Logger returns an instance of the logger for this wrapper.
77
+func (c *Conn) Logger() *zap.SugaredLogger {
78
+	return c.logger
79
+}
80
+
81
+// LocalAddr returns local address of the underlying net.Conn.
69
 func (c *Conn) LocalAddr() *net.TCPAddr {
82
 func (c *Conn) LocalAddr() *net.TCPAddr {
70
 	addr := c.conn.LocalAddr().(*net.TCPAddr)
83
 	addr := c.conn.LocalAddr().(*net.TCPAddr)
71
 	newAddr := *addr
84
 	newAddr := *addr
81
 	return &newAddr
94
 	return &newAddr
82
 }
95
 }
83
 
96
 
97
+// RemoteAddr returns remote address of the underlying net.Conn.
84
 func (c *Conn) RemoteAddr() *net.TCPAddr {
98
 func (c *Conn) RemoteAddr() *net.TCPAddr {
85
 	return c.conn.RemoteAddr().(*net.TCPAddr)
99
 	return c.conn.RemoteAddr().(*net.TCPAddr)
86
 }
100
 }
87
 
101
 
88
-func (c *Conn) Logger() *zap.SugaredLogger {
89
-	return c.logger
90
-}
91
-
102
+// NewConn initializes Conn wrapper for net.Conn.
92
 func NewConn(conn net.Conn, connID string, purpose ConnPurpose, publicIPv4, publicIPv6 net.IP) StreamReadWriteCloser {
103
 func NewConn(conn net.Conn, connID string, purpose ConnPurpose, publicIPv4, publicIPv6 net.IP) StreamReadWriteCloser {
93
 	logger := zap.S().With(
104
 	logger := zap.S().With(
94
 		"connection_id", connID,
105
 		"connection_id", connID,

+ 7
- 0
wrappers/mtproto_abridged.go View File

18
 	mtprotoAbridgedLargePacketLength = 16777216 // 256 ^ 3
18
 	mtprotoAbridgedLargePacketLength = 16777216 // 256 ^ 3
19
 )
19
 )
20
 
20
 
21
+// MTProtoAbridged presents abridged connection between client and
22
+// middle proxy.
21
 type MTProtoAbridged struct {
23
 type MTProtoAbridged struct {
22
 	conn   StreamReadWriteCloser
24
 	conn   StreamReadWriteCloser
23
 	opts   *mtproto.ConnectionOpts
25
 	opts   *mtproto.ConnectionOpts
127
 	return 0, errors.Errorf("Packet is too big %d", len(p))
129
 	return 0, errors.Errorf("Packet is too big %d", len(p))
128
 }
130
 }
129
 
131
 
132
+// Logger returns an instance of the logger for this wrapper.
130
 func (m *MTProtoAbridged) Logger() *zap.SugaredLogger {
133
 func (m *MTProtoAbridged) Logger() *zap.SugaredLogger {
131
 	return m.logger
134
 	return m.logger
132
 }
135
 }
133
 
136
 
137
+// LocalAddr returns local address of the underlying net.Conn.
134
 func (m *MTProtoAbridged) LocalAddr() *net.TCPAddr {
138
 func (m *MTProtoAbridged) LocalAddr() *net.TCPAddr {
135
 	return m.conn.LocalAddr()
139
 	return m.conn.LocalAddr()
136
 }
140
 }
137
 
141
 
142
+// RemoteAddr returns remote address of the underlying net.Conn.
138
 func (m *MTProtoAbridged) RemoteAddr() *net.TCPAddr {
143
 func (m *MTProtoAbridged) RemoteAddr() *net.TCPAddr {
139
 	return m.conn.RemoteAddr()
144
 	return m.conn.RemoteAddr()
140
 }
145
 }
141
 
146
 
147
+// Close closes underlying net.Conn instance.
142
 func (m *MTProtoAbridged) Close() error {
148
 func (m *MTProtoAbridged) Close() error {
143
 	return m.conn.Close()
149
 	return m.conn.Close()
144
 }
150
 }
145
 
151
 
152
+// NewMTProtoAbridged creates new wrapper for abridged client connection.
146
 func NewMTProtoAbridged(conn StreamReadWriteCloser, opts *mtproto.ConnectionOpts) PacketReadWriteCloser {
153
 func NewMTProtoAbridged(conn StreamReadWriteCloser, opts *mtproto.ConnectionOpts) PacketReadWriteCloser {
147
 	return &MTProtoAbridged{
154
 	return &MTProtoAbridged{
148
 		conn:   conn,
155
 		conn:   conn,

+ 13
- 11
wrappers/mtproto_cipher.go View File

4
 	"bytes"
4
 	"bytes"
5
 	"crypto/aes"
5
 	"crypto/aes"
6
 	"crypto/cipher"
6
 	"crypto/cipher"
7
-	"crypto/md5"
7
+	"crypto/md5" // nolint: gas
8
 	"crypto/sha1"
8
 	"crypto/sha1"
9
 	"encoding/binary"
9
 	"encoding/binary"
10
 	"net"
10
 	"net"
13
 	"github.com/9seconds/mtg/utils"
13
 	"github.com/9seconds/mtg/utils"
14
 )
14
 )
15
 
15
 
16
-type CipherPurpose uint8
16
+type cipherPurpose uint8
17
 
17
 
18
 const (
18
 const (
19
-	CipherPurposeClient CipherPurpose = iota
20
-	CipherPurposeServer
19
+	cipherPurposeClient cipherPurpose = iota
20
+	cipherPurposeServer
21
 )
21
 )
22
 
22
 
23
 var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
23
 var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
24
 
24
 
25
+// NewMiddleProxyCipher creates new block cipher to proxy<->telegram
26
+// connection.
25
 func NewMiddleProxyCipher(conn StreamReadWriteCloser, req *rpc.NonceRequest, resp *rpc.NonceResponse, secret []byte) StreamReadWriteCloser {
27
 func NewMiddleProxyCipher(conn StreamReadWriteCloser, req *rpc.NonceRequest, resp *rpc.NonceResponse, secret []byte) StreamReadWriteCloser {
26
 	localAddr := conn.LocalAddr()
28
 	localAddr := conn.LocalAddr()
27
 	remoteAddr := conn.RemoteAddr()
29
 	remoteAddr := conn.RemoteAddr()
28
 
30
 
29
-	encKey, encIV := deriveKeys(CipherPurposeClient, req, resp, localAddr, remoteAddr, secret)
30
-	decKey, decIV := deriveKeys(CipherPurposeServer, req, resp, localAddr, remoteAddr, secret)
31
+	encKey, encIV := deriveKeys(cipherPurposeClient, req, resp, localAddr, remoteAddr, secret)
32
+	decKey, decIV := deriveKeys(cipherPurposeServer, req, resp, localAddr, remoteAddr, secret)
31
 
33
 
32
 	enc, _ := makeEncrypterDecrypter(encKey, encIV)
34
 	enc, _ := makeEncrypterDecrypter(encKey, encIV)
33
 	_, dec := makeEncrypterDecrypter(decKey, decIV)
35
 	_, dec := makeEncrypterDecrypter(decKey, decIV)
35
 	return NewBlockCipher(conn, enc, dec)
37
 	return NewBlockCipher(conn, enc, dec)
36
 }
38
 }
37
 
39
 
38
-func deriveKeys(purpose CipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) ([]byte, []byte) {
40
+func deriveKeys(purpose cipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) ([]byte, []byte) {
39
 	message := bytes.Buffer{}
41
 	message := bytes.Buffer{}
40
 	message.Write(resp.Nonce[:])
42
 	message.Write(resp.Nonce[:])
41
 	message.Write(req.Nonce[:])
43
 	message.Write(req.Nonce[:])
54
 	message.Write(port[:])
56
 	message.Write(port[:])
55
 
57
 
56
 	switch purpose {
58
 	switch purpose {
57
-	case CipherPurposeClient:
59
+	case cipherPurposeClient:
58
 		message.WriteString("CLIENT")
60
 		message.WriteString("CLIENT")
59
-	case CipherPurposeServer:
61
+	case cipherPurposeServer:
60
 		message.WriteString("SERVER")
62
 		message.WriteString("SERVER")
61
 	default:
63
 	default:
62
 		panic("Unexpected cipher purpose")
64
 		panic("Unexpected cipher purpose")
75
 	message.Write(req.Nonce[:])
77
 	message.Write(req.Nonce[:])
76
 
78
 
77
 	data := message.Bytes()
79
 	data := message.Bytes()
78
-	md5sum := md5.Sum(data[1:])
80
+	md5sum := md5.Sum(data[1:]) // nolint: gas
79
 	sha1sum := sha1.Sum(data)
81
 	sha1sum := sha1.Sum(data)
80
 
82
 
81
 	key := append(md5sum[:12], sha1sum[:]...)
83
 	key := append(md5sum[:12], sha1sum[:]...)
82
-	iv := md5.Sum(data[2:])
84
+	iv := md5.Sum(data[2:]) // nolint: gas
83
 
85
 
84
 	return key, iv[:]
86
 	return key, iv[:]
85
 }
87
 }

+ 22
- 5
wrappers/mtproto_frame.go View File

20
 
20
 
21
 var mtprotoFramePadding = []byte{0x04, 0x00, 0x00, 0x00}
21
 var mtprotoFramePadding = []byte{0x04, 0x00, 0x00, 0x00}
22
 
22
 
23
+// MTProtoFrame is a wrapper which converts written data to the MTProtoFrame.
24
+// The format of the frame:
25
+//
26
+// [ MSGLEN(4) | SEQNO(4) | MSG(...) | CRC32(4) | PADDING(4*x) ]
27
+//
28
+// MSGLEN is the length of the message + len of seqno and msglen.
29
+// SEQNO is the number of frame in the receive/send sequence. If client
30
+//   sends a message with SeqNo 18, it has to receive message with SeqNo 18.
31
+// MSG is the data which has to be written
32
+// CRC32 is the CRC32 checksum of MSGLEN + SEQNO + MSG
33
+// PADDING is custom padding schema to complete frame length to such that
34
+//    len(frame) % 16 == 0
23
 type MTProtoFrame struct {
35
 type MTProtoFrame struct {
24
 	conn   StreamReadWriteCloser
36
 	conn   StreamReadWriteCloser
25
 	logger *zap.SugaredLogger
37
 	logger *zap.SugaredLogger
28
 	writeSeqNo int32
40
 	writeSeqNo int32
29
 }
41
 }
30
 
42
 
31
-func (m *MTProtoFrame) Read() ([]byte, error) {
43
+func (m *MTProtoFrame) Read() ([]byte, error) { // nolint: gocyclo
32
 	buf := &bytes.Buffer{}
44
 	buf := &bytes.Buffer{}
33
 	sum := crc32.NewIEEE()
45
 	sum := crc32.NewIEEE()
34
 	writer := io.MultiWriter(buf, sum)
46
 	writer := io.MultiWriter(buf, sum)
60
 	}
72
 	}
61
 
73
 
62
 	var seqNo int32
74
 	var seqNo int32
63
-	binary.Read(buf, binary.LittleEndian, &seqNo)
75
+	binary.Read(buf, binary.LittleEndian, &seqNo) // nolint: errcheck
64
 	if seqNo != m.readSeqNo {
76
 	if seqNo != m.readSeqNo {
65
 		return nil, errors.Errorf("Unexpected sequence number %d (wait for %d)", seqNo, m.readSeqNo)
77
 		return nil, errors.Errorf("Unexpected sequence number %d (wait for %d)", seqNo, m.readSeqNo)
66
 	}
78
 	}
96
 	buf := &bytes.Buffer{}
108
 	buf := &bytes.Buffer{}
97
 	buf.Grow(messageLength + paddingLength)
109
 	buf.Grow(messageLength + paddingLength)
98
 
110
 
99
-	binary.Write(buf, binary.LittleEndian, uint32(messageLength))
100
-	binary.Write(buf, binary.LittleEndian, m.writeSeqNo)
111
+	binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck
112
+	binary.Write(buf, binary.LittleEndian, m.writeSeqNo)          // nolint: errcheck
101
 	buf.Write(p)
113
 	buf.Write(p)
102
 
114
 
103
 	checksum := crc32.ChecksumIEEE(buf.Bytes())
115
 	checksum := crc32.ChecksumIEEE(buf.Bytes())
104
-	binary.Write(buf, binary.LittleEndian, checksum)
116
+	binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck
105
 	buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4))
117
 	buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4))
106
 
118
 
107
 	m.logger.Debugw("Write MTProto frame",
119
 	m.logger.Debugw("Write MTProto frame",
117
 	return len(p), err
129
 	return len(p), err
118
 }
130
 }
119
 
131
 
132
+// Logger returns an instance of the logger for this wrapper.
120
 func (m *MTProtoFrame) Logger() *zap.SugaredLogger {
133
 func (m *MTProtoFrame) Logger() *zap.SugaredLogger {
121
 	return m.logger
134
 	return m.logger
122
 }
135
 }
123
 
136
 
137
+// LocalAddr returns local address of the underlying net.Conn.
124
 func (m *MTProtoFrame) LocalAddr() *net.TCPAddr {
138
 func (m *MTProtoFrame) LocalAddr() *net.TCPAddr {
125
 	return m.conn.LocalAddr()
139
 	return m.conn.LocalAddr()
126
 }
140
 }
127
 
141
 
142
+// RemoteAddr returns remote address of the underlying net.Conn.
128
 func (m *MTProtoFrame) RemoteAddr() *net.TCPAddr {
143
 func (m *MTProtoFrame) RemoteAddr() *net.TCPAddr {
129
 	return m.conn.RemoteAddr()
144
 	return m.conn.RemoteAddr()
130
 }
145
 }
131
 
146
 
147
+// Close closes underlying net.Conn instance.
132
 func (m *MTProtoFrame) Close() error {
148
 func (m *MTProtoFrame) Close() error {
133
 	return m.conn.Close()
149
 	return m.conn.Close()
134
 }
150
 }
135
 
151
 
152
+// NewMTProtoFrame creates new PacketWrapper for underlying connection.
136
 func NewMTProtoFrame(conn StreamReadWriteCloser, seqNo int32) PacketReadWriteCloser {
153
 func NewMTProtoFrame(conn StreamReadWriteCloser, seqNo int32) PacketReadWriteCloser {
137
 	return &MTProtoFrame{
154
 	return &MTProtoFrame{
138
 		conn:       conn,
155
 		conn:       conn,

+ 8
- 0
wrappers/mtproto_intermediate.go View File

14
 
14
 
15
 const mtprotoIntermediateQuickAckLength = 0x80000000
15
 const mtprotoIntermediateQuickAckLength = 0x80000000
16
 
16
 
17
+// MTProtoIntermediate presents intermediate connection between client
18
+// and Telegram.
17
 type MTProtoIntermediate struct {
19
 type MTProtoIntermediate struct {
18
 	conn   StreamReadWriteCloser
20
 	conn   StreamReadWriteCloser
19
 	opts   *mtproto.ConnectionOpts
21
 	opts   *mtproto.ConnectionOpts
88
 	return m.conn.Write(append(length[:], p...))
90
 	return m.conn.Write(append(length[:], p...))
89
 }
91
 }
90
 
92
 
93
+// Logger returns an instance of the logger for this wrapper.
91
 func (m *MTProtoIntermediate) Logger() *zap.SugaredLogger {
94
 func (m *MTProtoIntermediate) Logger() *zap.SugaredLogger {
92
 	return m.logger
95
 	return m.logger
93
 }
96
 }
94
 
97
 
98
+// LocalAddr returns local address of the underlying net.Conn.
95
 func (m *MTProtoIntermediate) LocalAddr() *net.TCPAddr {
99
 func (m *MTProtoIntermediate) LocalAddr() *net.TCPAddr {
96
 	return m.conn.LocalAddr()
100
 	return m.conn.LocalAddr()
97
 }
101
 }
98
 
102
 
103
+// RemoteAddr returns remote address of the underlying net.Conn.
99
 func (m *MTProtoIntermediate) RemoteAddr() *net.TCPAddr {
104
 func (m *MTProtoIntermediate) RemoteAddr() *net.TCPAddr {
100
 	return m.conn.RemoteAddr()
105
 	return m.conn.RemoteAddr()
101
 }
106
 }
102
 
107
 
108
+// Close closes underlying net.Conn instance.
103
 func (m *MTProtoIntermediate) Close() error {
109
 func (m *MTProtoIntermediate) Close() error {
104
 	return m.conn.Close()
110
 	return m.conn.Close()
105
 }
111
 }
106
 
112
 
113
+// NewMTProtoIntermediate creates new PacketWrapper for intermediate
114
+// client connection.
107
 func NewMTProtoIntermediate(conn StreamReadWriteCloser, opts *mtproto.ConnectionOpts) PacketReadWriteCloser {
115
 func NewMTProtoIntermediate(conn StreamReadWriteCloser, opts *mtproto.ConnectionOpts) PacketReadWriteCloser {
108
 	return &MTProtoIntermediate{
116
 	return &MTProtoIntermediate{
109
 		conn:   conn,
117
 		conn:   conn,

+ 6
- 0
wrappers/mtproto_proxy.go View File

12
 	"github.com/9seconds/mtg/mtproto/rpc"
12
 	"github.com/9seconds/mtg/mtproto/rpc"
13
 )
13
 )
14
 
14
 
15
+// MTProtoProxy is a wrapper which creates/reads RPC responses from Telegram.
15
 type MTProtoProxy struct {
16
 type MTProtoProxy struct {
16
 	conn   PacketReadWriteCloser
17
 	conn   PacketReadWriteCloser
17
 	req    *rpc.ProxyRequest
18
 	req    *rpc.ProxyRequest
128
 	return len(p), nil
129
 	return len(p), nil
129
 }
130
 }
130
 
131
 
132
+// Logger returns an instance of the logger for this wrapper.
131
 func (m *MTProtoProxy) Logger() *zap.SugaredLogger {
133
 func (m *MTProtoProxy) Logger() *zap.SugaredLogger {
132
 	return m.logger
134
 	return m.logger
133
 }
135
 }
134
 
136
 
137
+// LocalAddr returns local address of the underlying net.Conn.
135
 func (m *MTProtoProxy) LocalAddr() *net.TCPAddr {
138
 func (m *MTProtoProxy) LocalAddr() *net.TCPAddr {
136
 	return m.conn.LocalAddr()
139
 	return m.conn.LocalAddr()
137
 }
140
 }
138
 
141
 
142
+// RemoteAddr returns remote address of the underlying net.Conn.
139
 func (m *MTProtoProxy) RemoteAddr() *net.TCPAddr {
143
 func (m *MTProtoProxy) RemoteAddr() *net.TCPAddr {
140
 	return m.conn.RemoteAddr()
144
 	return m.conn.RemoteAddr()
141
 }
145
 }
142
 
146
 
147
+// Close closes underlying net.Conn instance.
143
 func (m *MTProtoProxy) Close() error {
148
 func (m *MTProtoProxy) Close() error {
144
 	return m.conn.Close()
149
 	return m.conn.Close()
145
 }
150
 }
146
 
151
 
152
+// NewMTProtoProxy creates new RPC wrapper.
147
 func NewMTProtoProxy(conn PacketReadWriteCloser, connOpts *mtproto.ConnectionOpts, adTag []byte) (PacketReadWriteCloser, error) {
153
 func NewMTProtoProxy(conn PacketReadWriteCloser, connOpts *mtproto.ConnectionOpts, adTag []byte) (PacketReadWriteCloser, error) {
148
 	req, err := rpc.NewProxyRequest(connOpts.ClientAddr, conn.LocalAddr(), connOpts, adTag)
154
 	req, err := rpc.NewProxyRequest(connOpts.ClientAddr, conn.LocalAddr(), connOpts, adTag)
149
 	if err != nil {
155
 	if err != nil {

+ 7
- 0
wrappers/streamcipher.go View File

8
 	"go.uber.org/zap"
8
 	"go.uber.org/zap"
9
 )
9
 )
10
 
10
 
11
+// StreamCipher is a wrapper which encrypts/decrypts stream with AES-CTR
12
+// (as a part of obfuscated2 protocol).
11
 type StreamCipher struct {
13
 type StreamCipher struct {
12
 	encryptor cipher.Stream
14
 	encryptor cipher.Stream
13
 	decryptor cipher.Stream
15
 	decryptor cipher.Stream
32
 	return s.conn.Write(encrypted)
34
 	return s.conn.Write(encrypted)
33
 }
35
 }
34
 
36
 
37
+// Logger returns an instance of the logger for this wrapper.
35
 func (s *StreamCipher) Logger() *zap.SugaredLogger {
38
 func (s *StreamCipher) Logger() *zap.SugaredLogger {
36
 	return s.logger
39
 	return s.logger
37
 }
40
 }
38
 
41
 
42
+// LocalAddr returns local address of the underlying net.Conn.
39
 func (s *StreamCipher) LocalAddr() *net.TCPAddr {
43
 func (s *StreamCipher) LocalAddr() *net.TCPAddr {
40
 	return s.conn.LocalAddr()
44
 	return s.conn.LocalAddr()
41
 }
45
 }
42
 
46
 
47
+// RemoteAddr returns remote address of the underlying net.Conn.
43
 func (s *StreamCipher) RemoteAddr() *net.TCPAddr {
48
 func (s *StreamCipher) RemoteAddr() *net.TCPAddr {
44
 	return s.conn.RemoteAddr()
49
 	return s.conn.RemoteAddr()
45
 }
50
 }
46
 
51
 
52
+// Close closes underlying net.Conn instance.
47
 func (s *StreamCipher) Close() error {
53
 func (s *StreamCipher) Close() error {
48
 	return s.conn.Close()
54
 	return s.conn.Close()
49
 }
55
 }
50
 
56
 
57
+// NewStreamCipher creates new stream cipher wrapper.
51
 func NewStreamCipher(conn StreamReadWriteCloser, encryptor, decryptor cipher.Stream) StreamReadWriteCloser {
58
 func NewStreamCipher(conn StreamReadWriteCloser, encryptor, decryptor cipher.Stream) StreamReadWriteCloser {
52
 	return &StreamCipher{
59
 	return &StreamCipher{
53
 		conn:      conn,
60
 		conn:      conn,

+ 26
- 0
wrappers/wrap.go View File

7
 	"go.uber.org/zap"
7
 	"go.uber.org/zap"
8
 )
8
 )
9
 
9
 
10
+// Wrap is a base interface for all wrappers in this package.
10
 type Wrap interface {
11
 type Wrap interface {
11
 	Logger() *zap.SugaredLogger
12
 	Logger() *zap.SugaredLogger
12
 	LocalAddr() *net.TCPAddr
13
 	LocalAddr() *net.TCPAddr
13
 	RemoteAddr() *net.TCPAddr
14
 	RemoteAddr() *net.TCPAddr
14
 }
15
 }
15
 
16
 
17
+// Writer is a base interface for writers of this package.
16
 type Writer interface {
18
 type Writer interface {
17
 	io.Writer
19
 	io.Writer
18
 	Wrap
20
 	Wrap
19
 }
21
 }
20
 
22
 
23
+// Closer is a base interface for wrappers of this package which can
24
+// close connections.
21
 type Closer interface {
25
 type Closer interface {
22
 	io.Closer
26
 	io.Closer
23
 	Wrap
27
 	Wrap
24
 }
28
 }
25
 
29
 
30
+// WriteCloser is a base interface for wrappers of this package which
31
+// can write to and close connections.
26
 type WriteCloser interface {
32
 type WriteCloser interface {
27
 	io.Closer
33
 	io.Closer
28
 	Writer
34
 	Writer
29
 }
35
 }
30
 
36
 
37
+// StreamReader is a base interface for wrappers which can read from the
38
+// stream.
31
 type StreamReader interface {
39
 type StreamReader interface {
32
 	io.Reader
40
 	io.Reader
33
 	Wrap
41
 	Wrap
34
 }
42
 }
35
 
43
 
44
+// StreamReadCloser is a base interface for wrappers which can read from
45
+// and close the connections.
36
 type StreamReadCloser interface {
46
 type StreamReadCloser interface {
37
 	io.Closer
47
 	io.Closer
38
 	StreamReader
48
 	StreamReader
39
 }
49
 }
40
 
50
 
51
+// StreamReadWriter is a base interface for wrappers which can read from
52
+// and write to the connections.
41
 type StreamReadWriter interface {
53
 type StreamReadWriter interface {
42
 	io.Writer
54
 	io.Writer
43
 	StreamReader
55
 	StreamReader
44
 }
56
 }
45
 
57
 
58
+// StreamWriteCloser is a base interface for wrappers which can write to
59
+// and close the connections.
46
 type StreamWriteCloser interface {
60
 type StreamWriteCloser interface {
47
 	io.WriteCloser
61
 	io.WriteCloser
48
 	Wrap
62
 	Wrap
49
 }
63
 }
50
 
64
 
65
+// StreamReadWriteCloser is a base interface for stream processors.
51
 type StreamReadWriteCloser interface {
66
 type StreamReadWriteCloser interface {
52
 	io.Closer
67
 	io.Closer
53
 	StreamReadWriter
68
 	StreamReadWriter
54
 }
69
 }
55
 
70
 
71
+// PacketReader is a base interface for wrappers which reads 'packets'.
72
+// packets are atoms so you either get a packet or you get an error You
73
+// cannot resume reading from packet.
56
 type PacketReader interface {
74
 type PacketReader interface {
57
 	Read() ([]byte, error)
75
 	Read() ([]byte, error)
58
 	Wrap
76
 	Wrap
59
 }
77
 }
60
 
78
 
79
+// PacketWriter is a base interface for wrappers which can write packets.
61
 type PacketWriter interface {
80
 type PacketWriter interface {
62
 	io.Writer
81
 	io.Writer
63
 	Wrap
82
 	Wrap
64
 }
83
 }
65
 
84
 
85
+// PacketReadWriter is a base interface for wrappers which can read from
86
+// and write packets.
66
 type PacketReadWriter interface {
87
 type PacketReadWriter interface {
67
 	io.Writer
88
 	io.Writer
68
 	PacketReader
89
 	PacketReader
69
 }
90
 }
70
 
91
 
92
+// PacketReadCloser is a base interface for wrappers which can read
93
+// packets and close the connection.
71
 type PacketReadCloser interface {
94
 type PacketReadCloser interface {
72
 	io.Closer
95
 	io.Closer
73
 	PacketReader
96
 	PacketReader
74
 }
97
 }
75
 
98
 
99
+// PacketWriteCloser is a base interface for wrappers which can write
100
+// packets and close the connection.
76
 type PacketWriteCloser interface {
101
 type PacketWriteCloser interface {
77
 	io.Writer
102
 	io.Writer
78
 	io.Closer
103
 	io.Closer
79
 	Wrap
104
 	Wrap
80
 }
105
 }
81
 
106
 
107
+// PacketReadWriteCloser is a base interface for packet processors.
82
 type PacketReadWriteCloser interface {
108
 type PacketReadWriteCloser interface {
83
 	io.Closer
109
 	io.Closer
84
 	PacketReadWriter
110
 	PacketReadWriter

Loading…
Cancel
Save