Kaynağa Gözat

Add implementation of telegram dialer

tags/v2.0.0-rc1
9seconds 5 yıl önce
ebeveyn
işleme
7108fe99ec

+ 53
- 0
mtglib/internal/telegram/init.go Dosyayı Görüntüle

@@ -0,0 +1,53 @@
1
+package telegram
2
+
3
+import (
4
+	"context"
5
+	"net"
6
+)
7
+
8
+type preferIP uint8
9
+
10
+const (
11
+	preferIPOnlyIPv4 preferIP = iota
12
+	preferIPOnlyIPv6
13
+	preferIPPreferIPv4
14
+	preferIPPreferIPv6
15
+)
16
+
17
+type tgAddr struct {
18
+	network string
19
+	address string
20
+}
21
+
22
+// https://github.com/telegramdesktop/tdesktop/blob/master/Telegram/SourceFiles/mtproto/mtproto_dc_options.cpp#L30
23
+var (
24
+	v4Addresses = [5][]tgAddr{
25
+		{
26
+			{network: "tcp4", address: "149.154.175.50:443"},
27
+		},
28
+		{
29
+			{network: "tcp4", address: "149.154.167.51:443"},
30
+			{network: "tcp4", address: "95.161.76.100:443"},
31
+		},
32
+		{
33
+			{network: "tcp4", address: "149.154.175.100:443"},
34
+		},
35
+		{
36
+			{network: "tcp4", address: "149.154.167.91:443"},
37
+		},
38
+		{
39
+			{network: "tcp4", address: "149.154.171.5"},
40
+		},
41
+	}
42
+	v6Addresses = [5]tgAddr{
43
+		{network: "tcp6", address: "[2001:b28:f23d:f001::a]:443"},
44
+		{network: "tcp6", address: "[2001:67c:04e8:f002::a]:443"},
45
+		{network: "tcp6", address: "[2001:b28:f23d:f003::a]:443"},
46
+		{network: "tcp6", address: "[2001:67c:04e8:f004::a]:443"},
47
+		{network: "tcp6", address: "[2001:b28:f23f:f005::a]:443"},
48
+	}
49
+)
50
+
51
+type Dialer interface {
52
+	DialContext(ctx context.Context, network, address string) (net.Conn, error)
53
+}

+ 75
- 0
mtglib/internal/telegram/telegram.go Dosyayı Görüntüle

@@ -0,0 +1,75 @@
1
+package telegram
2
+
3
+import (
4
+	"context"
5
+	"fmt"
6
+	"math/rand"
7
+	"net"
8
+	"strings"
9
+)
10
+
11
+type Telegram struct {
12
+	dialer   Dialer
13
+	preferIP preferIP
14
+}
15
+
16
+func (t Telegram) Dial(ctx context.Context, dc int) (net.Conn, error) {
17
+	if dc < 0 || dc > 4 {
18
+		return nil, fmt.Errorf("do not know how to dial to %d", dc)
19
+	}
20
+
21
+	var addresses []tgAddr
22
+
23
+	if t.preferIP == preferIPOnlyIPv6 {
24
+		addresses = []tgAddr{v6Addresses[dc]}
25
+	} else {
26
+		addresses = append(addresses, v4Addresses[dc]...)
27
+		rand.Shuffle(len(addresses), func(i, j int) {
28
+			addresses[i], addresses[j] = addresses[j], addresses[i]
29
+		})
30
+	}
31
+
32
+	switch t.preferIP {
33
+	case preferIPPreferIPv4:
34
+		addresses = append(addresses, v6Addresses[dc])
35
+	case preferIPPreferIPv6:
36
+		addresses = append([]tgAddr{v6Addresses[dc]}, addresses...)
37
+	case preferIPOnlyIPv4, preferIPOnlyIPv6:
38
+	}
39
+
40
+	var (
41
+		conn net.Conn
42
+		err  error
43
+	)
44
+
45
+	for _, v := range addresses {
46
+		conn, err = t.dialer.DialContext(ctx, v.network, v.address)
47
+		if err == nil {
48
+			return conn, nil
49
+		}
50
+	}
51
+
52
+	return nil, fmt.Errorf("cannot dial to %d dc: %w", dc, err)
53
+}
54
+
55
+func NewTelegramDialer(dialer Dialer, ipPreference string) (*Telegram, error) {
56
+	var pref preferIP
57
+
58
+	switch strings.ToLower(ipPreference) {
59
+	case "prefer-ipv4":
60
+		pref = preferIPPreferIPv4
61
+	case "prefer-ipv6":
62
+		pref = preferIPPreferIPv6
63
+	case "only-ipv4":
64
+		pref = preferIPOnlyIPv4
65
+	case "only-ipv6":
66
+		pref = preferIPOnlyIPv6
67
+	default:
68
+		return nil, fmt.Errorf("unknown ip preference %s", ipPreference)
69
+	}
70
+
71
+	return &Telegram{
72
+		dialer:   dialer,
73
+		preferIP: pref,
74
+	}, nil
75
+}

+ 3
- 5
network/network.go Dosyayı Görüntüle

@@ -43,11 +43,9 @@ func (n *network) DialContext(ctx context.Context, protocol, address string) (ne
43 43
 		return nil, fmt.Errorf("cannot resolve dns names: %w", err)
44 44
 	}
45 45
 
46
-	if len(ips) > 1 {
47
-		rand.Shuffle(len(ips), func(i, j int) {
48
-			ips[i], ips[j] = ips[j], ips[i]
49
-		})
50
-	}
46
+	rand.Shuffle(len(ips), func(i, j int) {
47
+		ips[i], ips[j] = ips[j], ips[i]
48
+	})
51 49
 
52 50
 	var conn net.Conn
53 51
 	for _, v := range ips {

Loading…
İptal
Kaydet