Przeglądaj źródła

Add client abridged protocol

tags/1.0^2
9seconds 6 lat temu
rodzic
commit
e81c5970d4

+ 6
- 0
conntypes/acks.go Wyświetl plik

@@ -0,0 +1,6 @@
1
+package conntypes
2
+
3
+type ConnectionAcks struct {
4
+	Simple bool
5
+	Quick  bool
6
+}

+ 14
- 0
conntypes/wrap_interfaces.go Wyświetl plik

@@ -0,0 +1,14 @@
1
+package conntypes
2
+
3
+import (
4
+	"net"
5
+
6
+	"go.uber.org/zap"
7
+)
8
+
9
+type Wrap interface {
10
+	Conn() net.Conn
11
+	Logger() *zap.SugaredLogger
12
+	LocalAddr() *net.TCPAddr
13
+	RemoteAddr() *net.TCPAddr
14
+}

+ 41
- 0
conntypes/wrap_packet_ack_interfaces.go Wyświetl plik

@@ -0,0 +1,41 @@
1
+package conntypes
2
+
3
+import "io"
4
+
5
+type PacketAckReader interface {
6
+	Read(*ConnectionAcks) (Packet, error)
7
+}
8
+
9
+type PacketAckWriter interface {
10
+	Write(Packet, *ConnectionAcks) error
11
+}
12
+
13
+type PacketAckCloser interface {
14
+	io.Closer
15
+}
16
+
17
+type PacketAckReadCloser interface {
18
+	PacketAckReader
19
+	PacketAckCloser
20
+}
21
+
22
+type PacketAckWriteCloser interface {
23
+	PacketAckWriter
24
+	PacketAckCloser
25
+}
26
+
27
+type PacketAckReadWriter interface {
28
+	PacketAckReader
29
+	PacketAckWriter
30
+}
31
+
32
+type PacketAckReadWriteCloser interface {
33
+	PacketAckReader
34
+	PacketAckWriter
35
+	PacketAckCloser
36
+}
37
+
38
+type PacketAckFullReadWriteCloser interface {
39
+	Wrap
40
+	PacketAckReadWriteCloser
41
+}

+ 51
- 0
conntypes/wrap_packet_interfaces.go Wyświetl plik

@@ -0,0 +1,51 @@
1
+package conntypes
2
+
3
+import "io"
4
+
5
+type BasePacketReader interface {
6
+	Read() (Packet, error)
7
+}
8
+
9
+type BasePacketWriter interface {
10
+	Write(Packet) error
11
+}
12
+
13
+type PacketReader interface {
14
+	Wrap
15
+	BasePacketReader
16
+}
17
+
18
+type PacketWriter interface {
19
+	Wrap
20
+	BasePacketWriter
21
+}
22
+
23
+type PacketCloser interface {
24
+	Wrap
25
+	io.Closer
26
+}
27
+
28
+type PacketReadCloser interface {
29
+	Wrap
30
+	BasePacketReader
31
+	io.Closer
32
+}
33
+
34
+type PacketWriteCloser interface {
35
+	Wrap
36
+	BasePacketWriter
37
+	io.Closer
38
+}
39
+
40
+type PacketReadWriter interface {
41
+	Wrap
42
+	BasePacketWriter
43
+	BasePacketReader
44
+}
45
+
46
+type PacketReadWriteCloser interface {
47
+	Wrap
48
+	BasePacketWriter
49
+	BasePacketReader
50
+	io.Closer
51
+}

+ 56
- 0
conntypes/wrap_stream_interfaces.go Wyświetl plik

@@ -0,0 +1,56 @@
1
+package conntypes
2
+
3
+import (
4
+	"io"
5
+	"time"
6
+)
7
+
8
+type BaseStreamReaderWithTimeout interface {
9
+	ReadTimeout([]byte, time.Duration) (int, error)
10
+}
11
+
12
+type BaseStreamWriterWithTimeout interface {
13
+	WriteTimeout([]byte, time.Duration) (int, error)
14
+}
15
+
16
+type StreamReader interface {
17
+	Wrap
18
+	io.Reader
19
+	BaseStreamReaderWithTimeout
20
+}
21
+
22
+type StreamWriter interface {
23
+	Wrap
24
+	io.Writer
25
+	BaseStreamWriterWithTimeout
26
+}
27
+
28
+type StreamCloser interface {
29
+	Wrap
30
+	io.Closer
31
+}
32
+
33
+type StreamReadCloser interface {
34
+	Wrap
35
+	io.ReadCloser
36
+	BaseStreamReaderWithTimeout
37
+}
38
+
39
+type StreamWriteCloser interface {
40
+	Wrap
41
+	io.WriteCloser
42
+	BaseStreamWriterWithTimeout
43
+}
44
+
45
+type StreamReadWriter interface {
46
+	Wrap
47
+	io.ReadWriter
48
+	BaseStreamReaderWithTimeout
49
+}
50
+
51
+type StreamReadWriteCloser interface {
52
+	Wrap
53
+	io.ReadWriteCloser
54
+	BaseStreamReaderWithTimeout
55
+	BaseStreamWriterWithTimeout
56
+}

+ 0
- 113
conntypes/wrappers.go Wyświetl plik

@@ -1,115 +1,2 @@
1 1
 package conntypes
2 2
 
3
-import (
4
-	"io"
5
-	"net"
6
-	"time"
7
-
8
-	"go.uber.org/zap"
9
-)
10
-
11
-// Wrap is a base interface for all wrappers in this package.
12
-type Wrap interface {
13
-	Conn() net.Conn
14
-	Logger() *zap.SugaredLogger
15
-	LocalAddr() *net.TCPAddr
16
-	RemoteAddr() *net.TCPAddr
17
-}
18
-
19
-type BaseReaderWithTimeout interface {
20
-	ReadTimeout([]byte, time.Duration) (int, error)
21
-}
22
-
23
-type BaseWriterWithTimeout interface {
24
-	WriteTimeout([]byte, time.Duration) (int, error)
25
-}
26
-
27
-type BasePacketReader interface {
28
-	Read() (Packet, error)
29
-}
30
-
31
-type BasePacketWriter interface {
32
-	Write(Packet) error
33
-}
34
-
35
-type StreamReader interface {
36
-	Wrap
37
-	io.Reader
38
-	BaseReaderWithTimeout
39
-}
40
-
41
-type StreamWriter interface {
42
-	Wrap
43
-	io.Writer
44
-	BaseWriterWithTimeout
45
-}
46
-
47
-type StreamCloser interface {
48
-	Wrap
49
-	io.Closer
50
-}
51
-
52
-type StreamReadCloser interface {
53
-	Wrap
54
-	io.ReadCloser
55
-	BaseReaderWithTimeout
56
-}
57
-
58
-type StreamWriteCloser interface {
59
-	Wrap
60
-	io.WriteCloser
61
-	BaseWriterWithTimeout
62
-}
63
-
64
-type StreamReadWriter interface {
65
-	Wrap
66
-	io.ReadWriter
67
-	BaseReaderWithTimeout
68
-}
69
-
70
-type StreamReadWriteCloser interface {
71
-	Wrap
72
-	io.ReadWriteCloser
73
-	BaseReaderWithTimeout
74
-	BaseWriterWithTimeout
75
-}
76
-
77
-type PacketReader interface {
78
-	Wrap
79
-	BasePacketReader
80
-}
81
-
82
-type PacketWriter interface {
83
-	Wrap
84
-	BasePacketWriter
85
-}
86
-
87
-type PacketCloser interface {
88
-	Wrap
89
-	io.Closer
90
-}
91
-
92
-type PacketReadCloser interface {
93
-	Wrap
94
-	BasePacketReader
95
-	io.Closer
96
-}
97
-
98
-type PacketWriteCloser interface {
99
-	Wrap
100
-	BasePacketWriter
101
-	io.Closer
102
-}
103
-
104
-type PacketReadWriter interface {
105
-	Wrap
106
-	BasePacketWriter
107
-	BasePacketReader
108
-}
109
-
110
-type PacketReadWriteCloser interface {
111
-	Wrap
112
-	BasePacketWriter
113
-	BasePacketReader
114
-	io.Closer
115
-}

+ 4
- 0
go.mod Wyświetl plik

@@ -11,7 +11,10 @@ require (
11 11
 	github.com/cespare/xxhash v1.1.0
12 12
 	github.com/dustin/go-humanize v1.0.0
13 13
 	github.com/gammazero/deque v0.0.0-20190521012701-46e4ffb7a622
14
+	github.com/gofrs/uuid v3.2.0+incompatible
14 15
 	github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d
16
+	github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
17
+	github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b // indirect
15 18
 	github.com/kr/pretty v0.1.0 // indirect
16 19
 	github.com/pkg/errors v0.8.1
17 20
 	github.com/prometheus/client_golang v1.1.0
@@ -26,6 +29,7 @@ require (
26 29
 	gopkg.in/alecthomas/kingpin.v2 v2.2.6
27 30
 	gopkg.in/alexcesaro/statsd.v2 v2.0.0
28 31
 	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
32
+	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
29 33
 )
30 34
 
31 35
 go 1.13

+ 8
- 0
go.sum Wyświetl plik

@@ -32,6 +32,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
32 32
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
33 33
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
34 34
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
35
+github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
36
+github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
35 37
 github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
36 38
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
37 39
 github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
@@ -46,6 +48,10 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
46 48
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
47 49
 github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d h1:hJXjZMxj0SWlMoQkzeZDLi2cmeiWKa7y1B8Rg+qaoEc=
48 50
 github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
51
+github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
52
+github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
53
+github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b h1:Rrp0ByJXEjhREMPGTt3aWYjoIsUGCbt21ekbeJcTWv0=
54
+github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
49 55
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
50 56
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
51 57
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -128,6 +134,8 @@ gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7
128 134
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
129 135
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
130 136
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
137
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
138
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
131 139
 gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
132 140
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
133 141
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=

+ 15
- 2
hub/connection.go Wyświetl plik

@@ -7,6 +7,7 @@ import (
7 7
 
8 8
 	"github.com/9seconds/mtg/conntypes"
9 9
 	"github.com/9seconds/mtg/mtproto"
10
+	"github.com/9seconds/mtg/mtproto/rpc"
10 11
 	"github.com/9seconds/mtg/protocol"
11 12
 )
12 13
 
@@ -73,6 +74,8 @@ func (c *connection) idle() bool {
73 74
 }
74 75
 
75 76
 func (c *connection) run() {
77
+	logger := c.hub.logger.Named("connection").With("id", c.id)
78
+
76 79
 	for {
77 80
 		packet, err := c.read()
78 81
 		if err != nil {
@@ -80,8 +83,18 @@ func (c *connection) run() {
80 83
 			return
81 84
 		}
82 85
 
83
-		if channel, ok := Registry.getChannel(conntypes.ConnID{}); ok {
84
-			go channel.write(packet) // nolint: errcheck
86
+		response, err := rpc.ParseProxyResponse(packet)
87
+		if err != nil {
88
+			logger.Debugw("Failed response", "error", err)
89
+			continue
90
+		}
91
+		if response.Type == rpc.ProxyResponseTypeCloseExt {
92
+			logger.Debugw("Proxy has closed connection")
93
+			return
94
+		}
95
+
96
+		if channel, ok := Registry.getChannel(response.ConnID); ok {
97
+			go channel.sendBack(response) // nolint: errcheck
85 98
 		}
86 99
 	}
87 100
 }

+ 5
- 1
hub/connection_hub.go Wyświetl plik

@@ -3,6 +3,8 @@ package hub
3 3
 import (
4 4
 	"time"
5 5
 
6
+	"go.uber.org/zap"
7
+
6 8
 	"github.com/9seconds/mtg/protocol"
7 9
 )
8 10
 
@@ -15,6 +17,7 @@ type connectionHubRequest struct {
15 17
 
16 18
 type connectionHub struct {
17 19
 	sockets map[int]*connection
20
+	logger  *zap.SugaredLogger
18 21
 
19 22
 	channelBrokenSockets      chan int
20 23
 	channelConnectionRequests chan *connectionHubRequest
@@ -76,8 +79,9 @@ func (c *connectionHub) runReturnConnection(conn *connection) {
76 79
 	c.sockets[conn.id] = conn
77 80
 }
78 81
 
79
-func newConnectionHub() *connectionHub {
82
+func newConnectionHub(logger *zap.SugaredLogger) *connectionHub {
80 83
 	rv := &connectionHub{
84
+		logger:                    logger.Named("connection-hub"),
81 85
 		sockets:                   map[int]*connection{},
82 86
 		channelBrokenSockets:      make(chan int, 1),
83 87
 		channelConnectionRequests: make(chan *connectionHubRequest),

+ 7
- 7
hub/ctx_channel.go Wyświetl plik

@@ -4,23 +4,23 @@ import (
4 4
 	"context"
5 5
 	"time"
6 6
 
7
-	"github.com/9seconds/mtg/conntypes"
7
+	"github.com/9seconds/mtg/mtproto/rpc"
8 8
 )
9 9
 
10 10
 const closeableChannelReadTimeout = 2 * time.Minute
11 11
 
12 12
 type ChannelReadCloser interface {
13
-	Read() (conntypes.Packet, error)
13
+	Read() (*rpc.ProxyResponse, error)
14 14
 	Close() error
15 15
 }
16 16
 
17 17
 type ctxChannel struct {
18
-	channel chan conntypes.Packet
18
+	channel chan *rpc.ProxyResponse
19 19
 	ctx     context.Context
20 20
 	cancel  context.CancelFunc
21 21
 }
22 22
 
23
-func (c *ctxChannel) Read() (conntypes.Packet, error) {
23
+func (c *ctxChannel) Read() (*rpc.ProxyResponse, error) {
24 24
 	timer := time.NewTimer(closeableChannelReadTimeout)
25 25
 	defer timer.Stop()
26 26
 
@@ -34,11 +34,11 @@ func (c *ctxChannel) Read() (conntypes.Packet, error) {
34 34
 	}
35 35
 }
36 36
 
37
-func (c *ctxChannel) write(packet conntypes.Packet) error {
37
+func (c *ctxChannel) sendBack(response *rpc.ProxyResponse) error {
38 38
 	select {
39 39
 	case <-c.ctx.Done():
40 40
 		return ErrClosed
41
-	case c.channel <- packet:
41
+	case c.channel <- response:
42 42
 		return nil
43 43
 	}
44 44
 }
@@ -52,7 +52,7 @@ func (c *ctxChannel) Close() error {
52 52
 func newCtxChannel(ctx context.Context) *ctxChannel {
53 53
 	ctx, cancel := context.WithCancel(ctx)
54 54
 	return &ctxChannel{
55
-		channel: make(chan conntypes.Packet),
55
+		channel: make(chan *rpc.ProxyResponse),
56 56
 		ctx:     ctx,
57 57
 		cancel:  cancel,
58 58
 	}

+ 9
- 3
hub/hub.go Wyświetl plik

@@ -6,13 +6,16 @@ import (
6 6
 	"strings"
7 7
 	"sync"
8 8
 
9
+	"go.uber.org/zap"
10
+
9 11
 	"github.com/9seconds/mtg/conntypes"
10 12
 	"github.com/9seconds/mtg/protocol"
11 13
 )
12 14
 
13 15
 type hub struct {
14
-	subs  map[string]*connectionHub
15
-	mutex sync.RWMutex
16
+	logger *zap.SugaredLogger
17
+	subs   map[string]*connectionHub
18
+	mutex  sync.RWMutex
16 19
 }
17 20
 
18 21
 func (h *hub) Write(packet conntypes.Packet, req *protocol.TelegramRequest) error {
@@ -51,7 +54,10 @@ func (h *hub) getHub(req *protocol.TelegramRequest) *connectionHub {
51 54
 
52 55
 		rv, ok = h.subs[key]
53 56
 		if !ok {
54
-			rv = newConnectionHub()
57
+			rv = newConnectionHub(h.logger.With(
58
+				"dc", req.ClientProtocol.DC(),
59
+				"protocol", req.ClientProtocol.ConnectionProtocol(),
60
+			))
55 61
 			h.subs[key] = rv
56 62
 		}
57 63
 	}

+ 4
- 1
hub/init.go Wyświetl plik

@@ -4,6 +4,8 @@ import (
4 4
 	"context"
5 5
 	"errors"
6 6
 	"sync"
7
+
8
+	"go.uber.org/zap"
7 9
 )
8 10
 
9 11
 var (
@@ -24,7 +26,8 @@ func Init(ctx context.Context) {
24 26
 			ctx:   ctx,
25 27
 		}
26 28
 		Hub = &hub{
27
-			subs: map[string]*connectionHub{},
29
+			subs:   map[string]*connectionHub{},
30
+			logger: zap.S().Named("hub"),
28 31
 		}
29 32
 	})
30 33
 }

+ 5
- 4
mtproto/protocol.go Wyświetl plik

@@ -7,7 +7,8 @@ import (
7 7
 	"github.com/9seconds/mtg/mtproto/rpc"
8 8
 	"github.com/9seconds/mtg/protocol"
9 9
 	"github.com/9seconds/mtg/telegram"
10
-	"github.com/9seconds/mtg/wrappers"
10
+	"github.com/9seconds/mtg/wrappers/packet"
11
+	"github.com/9seconds/mtg/wrappers/stream"
11 12
 )
12 13
 
13 14
 func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteCloser, error) {
@@ -17,7 +18,7 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC
17 18
 		return nil, fmt.Errorf("cannot connect to telegram: %w", err)
18 19
 	}
19 20
 
20
-	rpcNonceConn := wrappers.NewMtprotoFrame(conn, rpc.SeqNoNonce)
21
+	rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce)
21 22
 	rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn)
22 23
 	if err != nil {
23 24
 		return nil, fmt.Errorf("cannot do nonce request: %w", err)
@@ -28,8 +29,8 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC
28 29
 		return nil, fmt.Errorf("cannot get nonce response: %w", err)
29 30
 	}
30 31
 
31
-	secureConn := wrappers.NewMiddleProxyCipher(conn, rpcNonceReq, rpcNonceResp, telegram.Middle.Secret())
32
-	frameConn := wrappers.NewMtprotoFrame(secureConn, rpc.SeqNoHandshake)
32
+	secureConn := stream.NewMiddleProxyCipher(conn, rpcNonceReq, rpcNonceResp, telegram.Middle.Secret())
33
+	frameConn := packet.NewMtprotoFrame(secureConn, rpc.SeqNoHandshake)
33 34
 
34 35
 	if err := doRPCHandshakeRequest(frameConn); err != nil {
35 36
 		return nil, fmt.Errorf("cannot do handshake request: %w", err)

+ 20
- 20
mtproto/rpc/proxy_flags.go Wyświetl plik

@@ -5,53 +5,53 @@ import (
5 5
 	"strings"
6 6
 )
7 7
 
8
-type proxyRequestFlags uint32
8
+type ProxyRequestFlags uint32
9 9
 
10 10
 const (
11
-	proxyRequestFlagsHasAdTag     proxyRequestFlags = 0x8
12
-	proxyRequestFlagsEncrypted    proxyRequestFlags = 0x2
13
-	proxyRequestFlagsMagic        proxyRequestFlags = 0x1000
14
-	proxyRequestFlagsExtMode2     proxyRequestFlags = 0x20000
15
-	proxyRequestFlagsIntermediate proxyRequestFlags = 0x20000000
16
-	proxyRequestFlagsAbdridged    proxyRequestFlags = 0x40000000
17
-	proxyRequestFlagsQuickAck     proxyRequestFlags = 0x80000000
18
-	proxyRequestFlagsPad          proxyRequestFlags = 0x8000000
11
+	ProxyRequestFlagsHasAdTag     ProxyRequestFlags = 0x8
12
+	ProxyRequestFlagsEncrypted    ProxyRequestFlags = 0x2
13
+	ProxyRequestFlagsMagic        ProxyRequestFlags = 0x1000
14
+	ProxyRequestFlagsExtMode2     ProxyRequestFlags = 0x20000
15
+	ProxyRequestFlagsIntermediate ProxyRequestFlags = 0x20000000
16
+	ProxyRequestFlagsAbdridged    ProxyRequestFlags = 0x40000000
17
+	ProxyRequestFlagsQuickAck     ProxyRequestFlags = 0x80000000
18
+	ProxyRequestFlagsPad          ProxyRequestFlags = 0x8000000
19 19
 )
20 20
 
21
-var proxyRequestFlagsEncryptedPrefix [8]byte
21
+var ProxyRequestFlagsEncryptedPrefix [8]byte
22 22
 
23
-func (r proxyRequestFlags) Bytes() []byte {
23
+func (r ProxyRequestFlags) Bytes() []byte {
24 24
 	converted := make([]byte, 4)
25 25
 	binary.LittleEndian.PutUint32(converted, uint32(r))
26 26
 
27 27
 	return converted
28 28
 }
29 29
 
30
-func (r proxyRequestFlags) String() string {
30
+func (r ProxyRequestFlags) String() string {
31 31
 	flags := make([]string, 0, 7)
32 32
 
33
-	if r&proxyRequestFlagsHasAdTag != 0 {
33
+	if r&ProxyRequestFlagsHasAdTag != 0 {
34 34
 		flags = append(flags, "HAS_AD_TAG")
35 35
 	}
36
-	if r&proxyRequestFlagsEncrypted != 0 {
36
+	if r&ProxyRequestFlagsEncrypted != 0 {
37 37
 		flags = append(flags, "ENCRYPTED")
38 38
 	}
39
-	if r&proxyRequestFlagsMagic != 0 {
39
+	if r&ProxyRequestFlagsMagic != 0 {
40 40
 		flags = append(flags, "MAGIC")
41 41
 	}
42
-	if r&proxyRequestFlagsExtMode2 != 0 {
42
+	if r&ProxyRequestFlagsExtMode2 != 0 {
43 43
 		flags = append(flags, "EXT_MODE_2")
44 44
 	}
45
-	if r&proxyRequestFlagsIntermediate != 0 {
45
+	if r&ProxyRequestFlagsIntermediate != 0 {
46 46
 		flags = append(flags, "INTERMEDIATE")
47 47
 	}
48
-	if r&proxyRequestFlagsAbdridged != 0 {
48
+	if r&ProxyRequestFlagsAbdridged != 0 {
49 49
 		flags = append(flags, "ABRIDGED")
50 50
 	}
51
-	if r&proxyRequestFlagsQuickAck != 0 {
51
+	if r&ProxyRequestFlagsQuickAck != 0 {
52 52
 		flags = append(flags, "QUICK_ACK")
53 53
 	}
54
-	if r&proxyRequestFlagsPad != 0 {
54
+	if r&ProxyRequestFlagsPad != 0 {
55 55
 		flags = append(flags, "PAD")
56 56
 	}
57 57
 

+ 51
- 0
mtproto/rpc/proxy_response.go Wyświetl plik

@@ -0,0 +1,51 @@
1
+package rpc
2
+
3
+import (
4
+	"bytes"
5
+	"fmt"
6
+
7
+	"github.com/9seconds/mtg/conntypes"
8
+)
9
+
10
+type ProxyResponseType uint8
11
+
12
+const (
13
+	ProxyResponseTypeAns ProxyResponseType = iota
14
+	ProxyResponseTypeSimpleAck
15
+	ProxyResponseTypeCloseExt
16
+)
17
+
18
+type ProxyResponse struct {
19
+	Type    ProxyResponseType
20
+	ConnID  conntypes.ConnID
21
+	Payload conntypes.Packet
22
+}
23
+
24
+func ParseProxyResponse(packet conntypes.Packet) (*ProxyResponse, error) {
25
+	var response ProxyResponse
26
+
27
+	if len(packet) < 4 {
28
+		return nil, fmt.Errorf("incorrect packet length: %d", len(packet))
29
+	}
30
+
31
+	tag := packet[:4]
32
+	switch {
33
+	case bytes.Equal(tag, TagProxyAns):
34
+		response.Type = ProxyResponseTypeAns
35
+		copy(response.ConnID[:], packet[8:16])
36
+		response.Payload = packet[16:]
37
+		return &response, nil
38
+
39
+	case bytes.Equal(tag, TagSimpleAck):
40
+		response.Type = ProxyResponseTypeSimpleAck
41
+		copy(response.ConnID[:], packet[4:12])
42
+		response.Payload = packet[12:]
43
+		return &response, nil
44
+
45
+	case bytes.Equal(tag, TagCloseExt):
46
+		response.Type = ProxyResponseTypeCloseExt
47
+		return &response, nil
48
+	}
49
+
50
+	return nil, fmt.Errorf("unknown response type %x", tag)
51
+}

+ 2
- 2
obfuscated2/client_protocol.go Wyświetl plik

@@ -14,7 +14,7 @@ import (
14 14
 	"github.com/9seconds/mtg/conntypes"
15 15
 	"github.com/9seconds/mtg/protocol"
16 16
 	"github.com/9seconds/mtg/utils"
17
-	"github.com/9seconds/mtg/wrappers"
17
+	"github.com/9seconds/mtg/wrappers/stream"
18 18
 )
19 19
 
20 20
 const clientProtocolHandshakeTimeout = 10 * time.Second
@@ -85,7 +85,7 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn
85 85
 	}
86 86
 	antireplay.Cache.Add(antiReplayKey)
87 87
 
88
-	return wrappers.NewObfuscated2(socket, encryptor, decryptor), nil
88
+	return stream.NewObfuscated2(socket, encryptor, decryptor), nil
89 89
 }
90 90
 
91 91
 func (c *ClientProtocol) ReadFrame(socket conntypes.StreamReader) (fm Frame, err error) {

+ 4
- 4
obfuscated2/telegram_protocol.go Wyświetl plik

@@ -8,7 +8,7 @@ import (
8 8
 	"github.com/9seconds/mtg/protocol"
9 9
 	"github.com/9seconds/mtg/telegram"
10 10
 	"github.com/9seconds/mtg/utils"
11
-	"github.com/9seconds/mtg/wrappers"
11
+	"github.com/9seconds/mtg/wrappers/stream"
12 12
 )
13 13
 
14 14
 func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteCloser, error) {
@@ -17,8 +17,8 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteC
17 17
 	if err != nil {
18 18
 		return nil, fmt.Errorf("cannot dial to telegram: %w", err)
19 19
 	}
20
-	conn = wrappers.NewTimeout(conn)
21
-	conn = wrappers.NewCtx(req.Ctx, req.Cancel, conn)
20
+	conn = stream.NewTimeout(conn)
21
+	conn = stream.NewCtx(req.Ctx, req.Cancel, conn)
22 22
 	fm := generateFrame(req.ClientProtocol)
23 23
 	data := fm.Bytes()
24 24
 
@@ -35,7 +35,7 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteC
35 35
 		return nil, fmt.Errorf("cannot write handshake frame to telegram: %w", err)
36 36
 	}
37 37
 
38
-	return wrappers.NewObfuscated2(conn, encryptor, decryptor), nil
38
+	return stream.NewObfuscated2(conn, encryptor, decryptor), nil
39 39
 }
40 40
 
41 41
 func generateFrame(cp protocol.ClientProtocol) (fm Frame) {

+ 4
- 4
proxy/proxy.go Wyświetl plik

@@ -14,7 +14,7 @@ import (
14 14
 	"github.com/9seconds/mtg/protocol"
15 15
 	"github.com/9seconds/mtg/stats"
16 16
 	"github.com/9seconds/mtg/utils"
17
-	"github.com/9seconds/mtg/wrappers"
17
+	"github.com/9seconds/mtg/wrappers/stream"
18 18
 )
19 19
 
20 20
 const directPipeBufferSize = 1024 * 1024
@@ -63,9 +63,9 @@ func (p *Proxy) accept(conn net.Conn) {
63 63
 	ctx, cancel := context.WithCancel(p.Context)
64 64
 	defer cancel()
65 65
 
66
-	clientConn := wrappers.NewClientConn(conn, connID)
67
-	clientConn = wrappers.NewCtx(ctx, cancel, clientConn)
68
-	clientConn = wrappers.NewTimeout(clientConn)
66
+	clientConn := stream.NewClientConn(conn, connID)
67
+	clientConn = stream.NewCtx(ctx, cancel, clientConn)
68
+	clientConn = stream.NewTimeout(clientConn)
69 69
 	defer clientConn.Close()
70 70
 
71 71
 	clientProtocol := p.ClientProtocolMaker()

+ 2
- 2
telegram/base.go Wyświetl plik

@@ -7,7 +7,7 @@ import (
7 7
 
8 8
 	"github.com/9seconds/mtg/conntypes"
9 9
 	"github.com/9seconds/mtg/utils"
10
-	"github.com/9seconds/mtg/wrappers"
10
+	"github.com/9seconds/mtg/wrappers/stream"
11 11
 )
12 12
 
13 13
 type baseTelegram struct {
@@ -44,7 +44,7 @@ func (b *baseTelegram) dial(dc conntypes.DC,
44 44
 		return nil, fmt.Errorf("cannot initialize tcp socket: %w", err)
45 45
 	}
46 46
 
47
-	return wrappers.NewTelegramConn(dc, conn), nil
47
+	return stream.NewTelegramConn(dc, conn), nil
48 48
 }
49 49
 
50 50
 func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string,

wrappers/mtproto_frame.go → wrappers/packet/mtproto_frame.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package packet
2 2
 
3 3
 import (
4 4
 	"bytes"

+ 119
- 0
wrappers/packetack/client_abridged.go Wyświetl plik

@@ -0,0 +1,119 @@
1
+package packetack
2
+
3
+import (
4
+	"bytes"
5
+	"fmt"
6
+	"io"
7
+	"net"
8
+
9
+	"go.uber.org/zap"
10
+
11
+	"github.com/9seconds/mtg/conntypes"
12
+	"github.com/9seconds/mtg/utils"
13
+)
14
+
15
+const (
16
+	clientAbridgedSmallPacketLength = 0x7f
17
+	clientAbridgedQuickAckLength    = 0x80
18
+	clientAbridgedLargePacketLength = 16777216 // 256 ^ 3
19
+)
20
+
21
+type wrapperClientAbridged struct {
22
+	parent conntypes.StreamReadWriteCloser
23
+}
24
+
25
+func (w *wrapperClientAbridged) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
26
+	buf := bytes.Buffer{}
27
+
28
+	if _, err := io.CopyN(&buf, w.parent, 1); err != nil {
29
+		return nil, fmt.Errorf("cannot read message length: %w", err)
30
+	}
31
+	msgLength := uint32(buf.Bytes()[0])
32
+	buf.Reset()
33
+
34
+	if msgLength >= clientAbridgedQuickAckLength {
35
+		acks.Quick = true
36
+		msgLength -= clientAbridgedQuickAckLength
37
+	}
38
+
39
+	if msgLength == clientAbridgedSmallPacketLength {
40
+		if _, err := io.CopyN(&buf, w.parent, 3); err != nil {
41
+			return nil, fmt.Errorf("cannot read correct message length: %w", err)
42
+		}
43
+		number := utils.Uint24{}
44
+		copy(number[:], buf.Bytes())
45
+		msgLength = utils.FromUint24(number)
46
+	}
47
+	msgLength *= 4
48
+
49
+	buf.Reset()
50
+	if _, err := io.CopyN(&buf, w.parent, int64(msgLength)); err != nil {
51
+		return nil, fmt.Errorf("cannot read message: %w", err)
52
+	}
53
+
54
+	return conntypes.Packet(buf.Bytes()), nil
55
+}
56
+
57
+func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error {
58
+	if len(packet)%4 != 0 {
59
+		return fmt.Errorf("incorrect packet length %d", len(packet))
60
+	}
61
+
62
+	if acks.Simple {
63
+		if _, err := w.parent.Write(utils.ReverseBytes(packet)); err != nil {
64
+			return fmt.Errorf("cannot send a simpleacked packet: %w", err)
65
+		}
66
+		return nil
67
+	}
68
+
69
+	packetLength := len(packet) / 4
70
+	switch {
71
+	case packetLength < clientAbridgedSmallPacketLength:
72
+		data := append([]byte{byte(packetLength)}, packet...)
73
+		if _, err := w.parent.Write(data); err != nil {
74
+			return fmt.Errorf("cannot send small packet: %w", err)
75
+		}
76
+		return nil
77
+
78
+	case packetLength < clientAbridgedLargePacketLength:
79
+		length24 := utils.ToUint24(uint32(packetLength))
80
+		buf := bytes.Buffer{}
81
+
82
+		buf.WriteByte(byte(clientAbridgedSmallPacketLength))
83
+		buf.Write(length24[:])
84
+		buf.Write(packet)
85
+
86
+		if _, err := w.parent.Write(buf.Bytes()); err != nil {
87
+			return fmt.Errorf("cannot send large packet: %w", err)
88
+		}
89
+		return nil
90
+	}
91
+
92
+	return fmt.Errorf("packet is too big: %d", len(packet))
93
+}
94
+
95
+func (w *wrapperClientAbridged) Close() error {
96
+	return w.parent.Close()
97
+}
98
+
99
+func (w *wrapperClientAbridged) Conn() net.Conn {
100
+	return w.parent.Conn()
101
+}
102
+
103
+func (w *wrapperClientAbridged) LocalAddr() *net.TCPAddr {
104
+	return w.parent.LocalAddr()
105
+}
106
+
107
+func (w *wrapperClientAbridged) RemoteAddr() *net.TCPAddr {
108
+	return w.parent.RemoteAddr()
109
+}
110
+
111
+func (w *wrapperClientAbridged) Logger() *zap.SugaredLogger {
112
+	return w.parent.Logger().Named("client-abridged")
113
+}
114
+
115
+func NewClientAbridged(parent conntypes.StreamReadWriteCloser) conntypes.PacketAckFullReadWriteCloser {
116
+	return &wrapperClientAbridged{
117
+		parent: parent,
118
+	}
119
+}

+ 99
- 0
wrappers/packetack/proxy.go Wyświetl plik

@@ -0,0 +1,99 @@
1
+package packetack
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/binary"
6
+	"fmt"
7
+	"net"
8
+
9
+	"github.com/9seconds/mtg/config"
10
+	"github.com/9seconds/mtg/conntypes"
11
+	"github.com/9seconds/mtg/hub"
12
+	"github.com/9seconds/mtg/mtproto/rpc"
13
+	"github.com/9seconds/mtg/protocol"
14
+)
15
+
16
+type wrapperProxy struct {
17
+	flags        rpc.ProxyRequestFlags
18
+	request      *protocol.TelegramRequest
19
+	clientIPPort []byte
20
+	ourIPPort    []byte
21
+	channelRead  hub.ChannelReadCloser
22
+}
23
+
24
+func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error {
25
+	buf := bytes.Buffer{}
26
+
27
+	flags := w.flags
28
+	if acks.Quick {
29
+		flags |= rpc.ProxyRequestFlagsQuickAck
30
+	}
31
+	if bytes.HasPrefix(packet, rpc.ProxyRequestFlagsEncryptedPrefix[:]) {
32
+		flags |= rpc.ProxyRequestFlagsEncrypted
33
+	}
34
+
35
+	buf.Write(rpc.TagProxyRequest)
36
+	buf.Write(flags.Bytes())
37
+	buf.Write(w.request.ConnID[:])
38
+	buf.Write(w.clientIPPort)
39
+	buf.Write(w.ourIPPort)
40
+	buf.Write(rpc.ProxyRequestExtraSize)
41
+	buf.Write(rpc.ProxyRequestProxyTag)
42
+	buf.WriteByte(byte(len(config.C.AdTag)))
43
+	buf.Write(config.C.AdTag)
44
+	buf.Write(make([]byte, (4-buf.Len()%4)%4))
45
+	buf.Write(packet)
46
+
47
+	return hub.Hub.Write(buf.Bytes(), w.request)
48
+}
49
+
50
+func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
51
+	resp, err := w.channelRead.Read()
52
+	if err != nil {
53
+		return nil, fmt.Errorf("cannot read a response: %w", err)
54
+	}
55
+
56
+	if resp.Type == rpc.ProxyResponseTypeSimpleAck {
57
+		acks.Simple = true
58
+	}
59
+
60
+	return resp.Payload, nil
61
+}
62
+
63
+func (w *wrapperProxy) Close() error {
64
+	return w.channelRead.Close()
65
+}
66
+
67
+func NewProxy(request *protocol.TelegramRequest) conntypes.PacketAckReadWriteCloser {
68
+	flags := rpc.ProxyRequestFlagsHasAdTag | rpc.ProxyRequestFlagsMagic | rpc.ProxyRequestFlagsExtMode2
69
+
70
+	switch request.ClientProtocol.ConnectionType() {
71
+	case conntypes.ConnectionTypeAbridged:
72
+		flags |= rpc.ProxyRequestFlagsAbdridged
73
+	case conntypes.ConnectionTypeIntermediate:
74
+		flags |= rpc.ProxyRequestFlagsIntermediate
75
+	case conntypes.ConnectionTypeSecure:
76
+		flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
77
+	default:
78
+		panic("unknown connection type")
79
+	}
80
+
81
+	return &wrapperProxy{
82
+		flags:        flags,
83
+		request:      request,
84
+		channelRead:  hub.Registry.Register(request.ConnID),
85
+		clientIPPort: proxyGetIPPort(request.ClientConn.RemoteAddr()),
86
+		ourIPPort:    proxyGetIPPort(request.ClientConn.LocalAddr()),
87
+	}
88
+}
89
+
90
+func proxyGetIPPort(addr *net.TCPAddr) []byte {
91
+	rv := [16 + 4]byte{}
92
+	port := [4]byte{}
93
+
94
+	copy(rv[:16], addr.IP.To16())
95
+	binary.LittleEndian.PutUint32(port[:], uint32(addr.Port))
96
+	copy(rv[16:], port[:])
97
+
98
+	return rv[:]
99
+}

wrappers/common.go → wrappers/stream/base.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"net"

wrappers/blockcipher.go → wrappers/stream/blockcipher.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"bytes"

wrappers/conn.go → wrappers/stream/conn.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"fmt"

wrappers/ctx.go → wrappers/stream/ctx.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"context"

wrappers/mtproto_cipher.go → wrappers/stream/mtproto_cipher.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"bytes"

wrappers/obfuscated2.go → wrappers/stream/obfuscated2.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"crypto/cipher"

wrappers/stats_telegram.go → wrappers/stream/stats_telegram.go Wyświetl plik

@@ -1,13 +1,14 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"net"
5 5
 	"sync"
6 6
 	"time"
7 7
 
8
+	"go.uber.org/zap"
9
+
8 10
 	"github.com/9seconds/mtg/conntypes"
9 11
 	"github.com/9seconds/mtg/stats"
10
-	"go.uber.org/zap"
11 12
 )
12 13
 
13 14
 type wrapperTelegramStats struct {

wrappers/stats_traffic.go → wrappers/stream/stats_traffic.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"net"

wrappers/timeout.go → wrappers/stream/timeout.go Wyświetl plik

@@ -1,4 +1,4 @@
1
-package wrappers
1
+package stream
2 2
 
3 3
 import (
4 4
 	"net"

Ładowanie…
Anuluj
Zapisz