Explorar el Código

Add telegram api

tags/1.0^2
9seconds hace 6 años
padre
commit
3816dbf5b1
Se han modificado 9 ficheros con 203 adiciones y 26 borrados
  1. 24
    0
      conntypes/id.go
  2. 1
    0
      go.mod
  3. 2
    0
      go.sum
  4. 2
    1
      protocol/request.go
  5. 2
    1
      proxy/proxy.go
  6. 106
    0
      telegram/api/addresses.go
  7. 38
    0
      telegram/api/api.go
  8. 23
    0
      telegram/api/secret.go
  9. 5
    24
      wrappers/wrapper_conn.go

+ 24
- 0
conntypes/id.go Ver fichero

1
+package conntypes
2
+
3
+import (
4
+	"crypto/rand"
5
+	"encoding/hex"
6
+)
7
+
8
+const ConnIDLength = 8
9
+
10
+type ConnID [ConnIDLength]byte
11
+
12
+func (c ConnID) String() string {
13
+	return hex.EncodeToString(c[:])
14
+}
15
+
16
+func NewConnID() ConnID {
17
+	var id ConnID
18
+
19
+	if _, err := rand.Read(id[:]); err != nil {
20
+		panic(err)
21
+	}
22
+
23
+	return id
24
+}

+ 1
- 0
go.mod Ver fichero

9
 	github.com/allegro/bigcache v1.2.1
9
 	github.com/allegro/bigcache v1.2.1
10
 	github.com/beevik/ntp v0.2.0
10
 	github.com/beevik/ntp v0.2.0
11
 	github.com/cespare/xxhash v1.1.0
11
 	github.com/cespare/xxhash v1.1.0
12
+	github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d
12
 	github.com/kr/pretty v0.1.0 // indirect
13
 	github.com/kr/pretty v0.1.0 // indirect
13
 	github.com/pkg/errors v0.8.1 // indirect
14
 	github.com/pkg/errors v0.8.1 // indirect
14
 	github.com/prometheus/client_golang v1.1.0
15
 	github.com/prometheus/client_golang v1.1.0

+ 2
- 0
go.sum Ver fichero

40
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
40
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
41
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
41
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
42
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
42
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
43
+github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d h1:hJXjZMxj0SWlMoQkzeZDLi2cmeiWKa7y1B8Rg+qaoEc=
44
+github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
43
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
45
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
44
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
46
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
45
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
47
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=

+ 2
- 1
protocol/request.go Ver fichero

5
 
5
 
6
 	"go.uber.org/zap"
6
 	"go.uber.org/zap"
7
 
7
 
8
+	"github.com/9seconds/mtg/conntypes"
8
 	"github.com/9seconds/mtg/wrappers"
9
 	"github.com/9seconds/mtg/wrappers"
9
 )
10
 )
10
 
11
 
11
 type TelegramRequest struct {
12
 type TelegramRequest struct {
12
 	Logger         *zap.SugaredLogger
13
 	Logger         *zap.SugaredLogger
13
 	ClientConn     wrappers.StreamReadWriteCloser
14
 	ClientConn     wrappers.StreamReadWriteCloser
14
-	ConnID         wrappers.ConnID
15
+	ConnID         conntypes.ConnID
15
 	Ctx            context.Context
16
 	Ctx            context.Context
16
 	Cancel         context.CancelFunc
17
 	Cancel         context.CancelFunc
17
 	ClientProtocol ClientProtocol
18
 	ClientProtocol ClientProtocol

+ 2
- 1
proxy/proxy.go Ver fichero

9
 	"go.uber.org/zap"
9
 	"go.uber.org/zap"
10
 
10
 
11
 	"github.com/9seconds/mtg/config"
11
 	"github.com/9seconds/mtg/config"
12
+	"github.com/9seconds/mtg/conntypes"
12
 	"github.com/9seconds/mtg/protocol"
13
 	"github.com/9seconds/mtg/protocol"
13
 	"github.com/9seconds/mtg/stats"
14
 	"github.com/9seconds/mtg/stats"
14
 	"github.com/9seconds/mtg/telegram"
15
 	"github.com/9seconds/mtg/telegram"
53
 		}
54
 		}
54
 	}()
55
 	}()
55
 
56
 
56
-	connID := wrappers.NewConnID()
57
+	connID := conntypes.NewConnID()
57
 	logger := p.Logger.With("connection_id", connID)
58
 	logger := p.Logger.With("connection_id", connID)
58
 
59
 
59
 	if err := utils.InitTCP(conn); err != nil {
60
 	if err := utils.InitTCP(conn); err != nil {

+ 106
- 0
telegram/api/addresses.go Ver fichero

1
+package api
2
+
3
+import (
4
+	"bufio"
5
+	"fmt"
6
+	"net"
7
+	"regexp"
8
+	"strconv"
9
+	"strings"
10
+
11
+	"github.com/9seconds/mtg/conntypes"
12
+)
13
+
14
+const (
15
+	addressesURLV4 = "https://core.telegram.org/getProxyConfig"   // nolint: gas
16
+	addressesURLV6 = "https://core.telegram.org/getProxyConfigV6" // nolint: gas
17
+)
18
+
19
+var addressesProxyForSplitter = regexp.MustCompile(`\s+`)
20
+
21
+func AddressesV4() (map[conntypes.DC][]string, conntypes.DC, error) {
22
+	return getAddresses(addressesURLV4)
23
+}
24
+
25
+func AddressesV6() (map[conntypes.DC][]string, conntypes.DC, error) {
26
+	return getAddresses(addressesURLV6)
27
+}
28
+
29
+func getAddresses(url string) (map[conntypes.DC][]string, conntypes.DC, error) {
30
+	resp, err := request(url)
31
+	if err != nil {
32
+		return nil, 0, fmt.Errorf("cannot get http response: %w", err)
33
+	}
34
+	defer resp.Close()
35
+
36
+	scanner := bufio.NewScanner(resp)
37
+	data := map[conntypes.DC][]string{}
38
+
39
+	var defaultDC = conntypes.DCDefaultIdx
40
+	for scanner.Scan() {
41
+		text := strings.TrimSpace(scanner.Text())
42
+		switch {
43
+		case strings.HasPrefix(text, "#"):
44
+			continue
45
+
46
+		case strings.HasPrefix(text, "proxy_for"):
47
+			addr, idx, err := addressesParseProxyFor(text)
48
+			if err != nil {
49
+				return nil, 0, fmt.Errorf("cannot parse 'proxy_for' section: %w", err)
50
+			}
51
+			if addresses, ok := data[idx]; ok {
52
+				data[idx] = append(addresses, addr)
53
+			} else {
54
+				data[idx] = []string{addr}
55
+			}
56
+
57
+		case strings.HasPrefix(text, "default"):
58
+			idx, err := addressesParseDefault(text)
59
+			if err != nil {
60
+				return nil, 0, fmt.Errorf("cannot parse 'default' section: %w", err)
61
+			}
62
+			defaultDC = idx
63
+		}
64
+	}
65
+
66
+	err = scanner.Err()
67
+	if err != nil {
68
+		return nil, 0, fmt.Errorf("cannot parse http response: %w", err)
69
+	}
70
+
71
+	return data, defaultDC, nil
72
+}
73
+
74
+func addressesParseProxyFor(text string) (string, conntypes.DC, error) {
75
+	chunks := addressesProxyForSplitter.Split(text, 3)
76
+	if len(chunks) != 3 || chunks[0] != "proxy_for" {
77
+		return "", 0, fmt.Errorf("incorrect config %s", text)
78
+	}
79
+
80
+	dc, err := strconv.ParseInt(chunks[1], 10, 16)
81
+	if err != nil {
82
+		return "", 0, fmt.Errorf("incorrect config '%s': %w", text, err)
83
+	}
84
+
85
+	addr := strings.TrimRight(chunks[2], ";")
86
+	if _, _, err = net.SplitHostPort(addr); err != nil {
87
+		return "", 0, fmt.Errorf("incorrect config '%s': %w", text, err)
88
+	}
89
+
90
+	return addr, conntypes.DC(dc), nil
91
+}
92
+
93
+func addressesParseDefault(text string) (conntypes.DC, error) {
94
+	chunks := addressesProxyForSplitter.Split(text, 2)
95
+	if len(chunks) != 2 || chunks[0] != "default" {
96
+		return 0, fmt.Errorf("incorrect config '%s'", text)
97
+	}
98
+
99
+	dcString := strings.TrimRight(chunks[1], ";")
100
+	dc, err := strconv.ParseInt(dcString, 10, 16)
101
+	if err != nil {
102
+		return 0, fmt.Errorf("incorrect config '%s': %w", text, err)
103
+	}
104
+
105
+	return conntypes.DC(dc), nil
106
+}

+ 38
- 0
telegram/api/api.go Ver fichero

1
+package api
2
+
3
+import (
4
+	"fmt"
5
+	"io"
6
+	"io/ioutil"
7
+	"net/http"
8
+	"time"
9
+)
10
+
11
+const (
12
+	apiUserAgent   = "mtg"
13
+	apiHTTPTimeout = 30 * time.Second
14
+)
15
+
16
+var httpClient = http.Client{
17
+	Timeout: apiHTTPTimeout,
18
+}
19
+
20
+func request(url string) (io.ReadCloser, error) {
21
+	req, err := http.NewRequest("GET", url, nil)
22
+	if err != nil {
23
+		panic(err)
24
+	}
25
+	req.Header.Set("Accept", "text/plan")
26
+	req.Header.Set("User-Agent", apiUserAgent)
27
+
28
+	resp, err := httpClient.Do(req)
29
+	if err != nil {
30
+		if resp != nil {
31
+			io.Copy(ioutil.Discard, resp.Body)
32
+			resp.Body.Close()
33
+		}
34
+		return nil, fmt.Errorf("cannot perform a request: %w", err)
35
+	}
36
+
37
+	return resp.Body, err
38
+}

+ 23
- 0
telegram/api/secret.go Ver fichero

1
+package api
2
+
3
+import (
4
+	"fmt"
5
+	"io/ioutil"
6
+)
7
+
8
+const secretURL = "https://core.telegram.org/getProxySecret" // nolint: gas
9
+
10
+func Secret() ([]byte, error) {
11
+	resp, err := request(secretURL)
12
+	if err != nil {
13
+		return nil, fmt.Errorf("cannot access telegram server: %w", err)
14
+	}
15
+	defer resp.Close()
16
+
17
+	secret, err := ioutil.ReadAll(resp)
18
+	if err != nil {
19
+		return nil, fmt.Errorf("cannot read response: %w", err)
20
+	}
21
+
22
+	return secret, nil
23
+}

+ 5
- 24
wrappers/wrapper_conn.go Ver fichero

2
 
2
 
3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
-	"crypto/rand"
6
-	"encoding/hex"
7
 	"fmt"
5
 	"fmt"
8
 	"net"
6
 	"net"
9
 	"time"
7
 	"time"
11
 	"go.uber.org/zap"
9
 	"go.uber.org/zap"
12
 
10
 
13
 	"github.com/9seconds/mtg/config"
11
 	"github.com/9seconds/mtg/config"
12
+	"github.com/9seconds/mtg/conntypes"
14
 )
13
 )
15
 
14
 
16
-const ConnIDLength = 8
17
-
18
-type ConnID [ConnIDLength]byte
19
-
20
-func (c ConnID) String() string {
21
-	return hex.EncodeToString(c[:])
22
-}
23
-
24
 type connPurpose uint8
15
 type connPurpose uint8
25
 
16
 
26
 const (
17
 const (
37
 	parent     net.Conn
28
 	parent     net.Conn
38
 	ctx        context.Context
29
 	ctx        context.Context
39
 	cancel     context.CancelFunc
30
 	cancel     context.CancelFunc
40
-	connID     ConnID
31
+	connID     conntypes.ConnID
41
 	logger     *zap.SugaredLogger
32
 	logger     *zap.SugaredLogger
42
 	localAddr  *net.TCPAddr
33
 	localAddr  *net.TCPAddr
43
 	remoteAddr *net.TCPAddr
34
 	remoteAddr *net.TCPAddr
121
 func newConn(ctx context.Context,
112
 func newConn(ctx context.Context,
122
 	cancel context.CancelFunc,
113
 	cancel context.CancelFunc,
123
 	parent net.Conn,
114
 	parent net.Conn,
124
-	connID ConnID,
115
+	connID conntypes.ConnID,
125
 	purpose connPurpose) StreamReadWriteCloser {
116
 	purpose connPurpose) StreamReadWriteCloser {
126
 	localAddr := *parent.LocalAddr().(*net.TCPAddr)
117
 	localAddr := *parent.LocalAddr().(*net.TCPAddr)
127
 
118
 
156
 func NewClientConn(ctx context.Context,
147
 func NewClientConn(ctx context.Context,
157
 	cancel context.CancelFunc,
148
 	cancel context.CancelFunc,
158
 	parent net.Conn,
149
 	parent net.Conn,
159
-	connID ConnID) StreamReadWriteCloser {
150
+	connID conntypes.ConnID) StreamReadWriteCloser {
160
 	return newConn(ctx, cancel, parent, connID, connPurposeClient)
151
 	return newConn(ctx, cancel, parent, connID, connPurposeClient)
161
 }
152
 }
162
 
153
 
163
 func NewTelegramConn(ctx context.Context,
154
 func NewTelegramConn(ctx context.Context,
164
 	cancel context.CancelFunc,
155
 	cancel context.CancelFunc,
165
 	parent net.Conn) StreamReadWriteCloser {
156
 	parent net.Conn) StreamReadWriteCloser {
166
-	return newConn(ctx, cancel, parent, ConnID{}, connPurposeTelegram)
167
-}
168
-
169
-func NewConnID() ConnID {
170
-	var id ConnID
171
-
172
-	if _, err := rand.Read(id[:]); err != nil {
173
-		panic(err)
174
-	}
175
-
176
-	return id
157
+	return newConn(ctx, cancel, parent, conntypes.ConnID{}, connPurposeTelegram)
177
 }
158
 }

Loading…
Cancelar
Guardar