1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-08 05:47:07 +09:00

GO-3886 Merge branch 'release-6' of ssh://github.com/anyproto/anytype-heart into go-3886-add-p2p-restricted-status

# Conflicts:
#	go.mod
#	go.sum
#	pb/commands.pb.go
#	pb/events.pb.go
This commit is contained in:
Roman Khafizianov 2024-08-30 01:29:38 +02:00
commit 2f5ecbb156
No known key found for this signature in database
GPG key ID: F07A7D55A2684852
13 changed files with 1518 additions and 1141 deletions

View file

@ -5,6 +5,7 @@ import (
"errors"
"os"
"path/filepath"
"runtime"
trace2 "runtime/trace"
"strings"
@ -40,9 +41,10 @@ func (s *Service) AccountSelect(ctx context.Context, req *pb.RpcAccountSelectReq
return nil, ErrEmptyAccountID
}
s.traceRecorder.start()
defer s.traceRecorder.stop()
if runtime.GOOS != "android" && runtime.GOOS != "ios" {
s.traceRecorder.start()
defer s.traceRecorder.stop()
}
s.cancelStartIfInProcess()
s.lock.Lock()
defer s.lock.Unlock()

View file

@ -13,6 +13,7 @@ import (
"sync"
"time"
"github.com/klauspost/compress/flate"
exptrace "golang.org/x/exp/trace"
"github.com/anyproto/anytype-heart/util/debug"
@ -91,6 +92,9 @@ type zipFile struct {
func createZipArchive(w io.Writer, files []zipFile) error {
zipw := zip.NewWriter(w)
zipw.RegisterCompressor(zip.Deflate, func(w io.Writer) (io.WriteCloser, error) {
return flate.NewWriter(w, flate.BestSpeed)
})
err := func() error {
for _, file := range files {
f, err := zipw.Create(file.name)
@ -107,8 +111,8 @@ func createZipArchive(w io.Writer, files []zipFile) error {
return errors.Join(err, zipw.Close())
}
func (s *Service) SaveLoginTrace() (string, error) {
return s.traceRecorder.save()
func (s *Service) SaveLoginTrace(dir string) (string, error) {
return s.traceRecorder.save(dir)
}
// traceRecorder is a helper to start and stop flight trace recorder
@ -118,7 +122,8 @@ type traceRecorder struct {
lastRecordedBuf *bytes.Buffer // contains zip archive of trace
}
func (r *traceRecorder) save() (string, error) {
// empty dir means use system temp dir
func (r *traceRecorder) save(dir string) (string, error) {
r.lock.Lock()
defer r.lock.Unlock()
@ -138,7 +143,7 @@ func (r *traceRecorder) save() (string, error) {
traceReader = buf
}
f, err := os.CreateTemp("", "account-select-trace-*.zip")
f, err := os.CreateTemp(dir, "account-select-trace-*.zip")
if err != nil {
return "", fmt.Errorf("create temp file: %w", err)
}

View file

@ -224,7 +224,7 @@ func (mw *Middleware) DebugRunProfiler(cctx context.Context, req *pb.RpcDebugRun
}
func (mw *Middleware) DebugAccountSelectTrace(cctx context.Context, req *pb.RpcDebugAccountSelectTraceRequest) *pb.RpcDebugAccountSelectTraceResponse {
path, err := mw.applicationService.SaveLoginTrace()
path, err := mw.applicationService.SaveLoginTrace(req.Dir)
if err != nil {
return &pb.RpcDebugAccountSelectTraceResponse{
Error: &pb.RpcDebugAccountSelectTraceResponseError{

View file

@ -9741,6 +9741,11 @@ Get marks list in the selected range in text block.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| dir | [string](#string) | | empty means using OS-provided temp dir |

View file

@ -1,15 +1,22 @@
package addrs
import (
"cmp"
"fmt"
"net"
"regexp"
"runtime"
"strconv"
"strings"
"golang.org/x/exp/slices"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
"github.com/anyproto/anytype-heart/util/slice"
)
var log = logging.Logger("anytype-net")
type Interface struct {
net.Interface
Addrs []InterfaceAddr
@ -20,9 +27,54 @@ type InterfaceAddr struct {
Prefix int
}
type NetInterfaceWithAddrCache struct {
net.Interface
cachedAddrs []net.Addr // ipv4 addresses
cachedErr error
}
type InterfacesAddrs struct {
Interfaces []net.Interface
Addrs []net.Addr
Interfaces []NetInterfaceWithAddrCache
Addrs []net.Addr // addrs without attachment to specific interface. Used as a fallback mechanism
}
func WrapInterface(iface net.Interface) NetInterfaceWithAddrCache {
return NetInterfaceWithAddrCache{
Interface: iface,
}
}
func WrapInterfaces(ifaces []net.Interface) []NetInterfaceWithAddrCache {
var m = make([]NetInterfaceWithAddrCache, 0, len(ifaces))
for i := range ifaces {
m = append(m, NetInterfaceWithAddrCache{
Interface: ifaces[i],
})
}
return m
}
// GetAddr returns ipv4 only addresses for interface or cached one if set
func (i NetInterfaceWithAddrCache) GetAddr() []net.Addr {
if i.cachedAddrs != nil {
return i.cachedAddrs
}
if i.cachedErr != nil {
return nil
}
i.cachedAddrs, i.cachedErr = i.Interface.Addrs()
if i.cachedErr != nil {
log.Warn("interface GetAddr error: %v", i.cachedErr)
}
// filter-out ipv6
i.cachedAddrs = slice.Filter(i.cachedAddrs, func(addr net.Addr) bool {
if ip, ok := addr.(*net.IPNet); ok {
if ip.IP.To4() == nil {
return false
}
}
return true
})
return i.cachedAddrs
}
func (i InterfacesAddrs) Equal(other InterfacesAddrs) bool {
@ -34,35 +86,110 @@ func (i InterfacesAddrs) Equal(other InterfacesAddrs) bool {
}
myStr := getStrings(i)
otherStr := getStrings(other)
return slices.Equal(myStr, otherStr)
// compare slices without order
if !slices.Equal(myStr, otherStr) {
log.Debug(fmt.Sprintf("addrs compare: strings mismatch: %v != %v", myStr, otherStr))
return false
}
return true
}
var (
ifaceRe = regexp.MustCompile(`^([a-z]*?)([0-9]+)$`)
ifaceRe = regexp.MustCompile(`^([a-z]*?)([0-9]+)$`)
ifaceWindowsRe = regexp.MustCompile(`^(.*?)([0-9]*)$`)
// ifaceReBusSlot used for prefixBusSlot naming schema used in newer linux distros https://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n20
ifaceReBusSlot = regexp.MustCompile(`^([a-z]*?)p([0-9]+)s([0-9a-f]+)$`)
ifaceReBusSlot = regexp.MustCompile(`^(?P<type>enp|eno|ens|enx|wlp|wlx)(?P<bus>[0-9a-fA-F]*)s?(?P<slot>[0-9a-fA-F]*)?$`)
)
func parseInterfaceName(name string) (prefix string, bus int, num int64) {
func cleanInterfaceName(name string) (clean string, namingType NamingType) {
if strings.HasPrefix(name, "en") ||
strings.HasPrefix(name, "wl") ||
strings.HasPrefix(name, "eth") {
lastSymbol := name[len(name)-1]
switch NamingType(lastSymbol) {
case NamingTypeBusSlot, NamingTypeHotplug, NamingTypeMac, NamingTypeOnboard:
return name[0 : len(name)-1], NamingType(lastSymbol)
}
}
return name, NamingTypeOld
}
type NamingType string
const (
NamingTypeOld NamingType = ""
NamingTypeOnboard NamingType = "o"
NamingTypeBusSlot NamingType = "p"
NamingTypeMac NamingType = "x"
NamingTypeHotplug NamingType = "s"
)
func (n NamingType) Priority() int {
switch n {
case NamingTypeOld:
return 0
case NamingTypeOnboard:
return 1
case NamingTypeBusSlot:
return 2
case NamingTypeMac:
return 3
case NamingTypeHotplug:
return 4
default:
return 5
}
}
// parseInterfaceName parses interface name and returns prefix, naming type, bus number and slot number
// e.g. enp0s3 -> en, NamingTypeBusSlot, 0, 3
// bus and slot are interpreted as hex numbers
// bus is also used for mac address
// in case of enx001122334455 -> en, NamingTypeMac, 0x001122334455, 0
func parseInterfaceName(name string) (iface string, namingType NamingType, busNum int64, num int64) {
if runtime.GOOS == "windows" {
name, num = parseInterfaceWindowsName(name)
return
}
// try new-style naming schema first (enp0s3, wlp2s0, ...)
res := ifaceReBusSlot.FindStringSubmatch(name)
if len(res) > 0 {
if len(res) > 1 {
prefix = res[1]
}
if len(res) > 2 {
bus, _ = strconv.Atoi(res[2])
}
if len(res) > 3 {
numHex := res[3]
num, _ = strconv.ParseInt(numHex, 16, 32)
for i, subName := range ifaceReBusSlot.SubexpNames() {
if i > 0 && res[i] != "" {
switch subName {
case "type":
iface, namingType = cleanInterfaceName(res[i])
case "bus":
busNum, _ = strconv.ParseInt(res[i], 16, 64)
case "slot": // or mac
num, _ = strconv.ParseInt(res[i], 16, 64)
}
}
}
return
}
// try old-style naming schema (eth0, wlan0, ...)
res = ifaceRe.FindStringSubmatch(name)
if len(res) > 1 {
prefix = res[1]
iface = res[1]
}
if len(res) > 2 {
num, _ = strconv.ParseInt(res[2], 10, 32)
}
if iface == "" {
}
return
}
func parseInterfaceWindowsName(name string) (iface string, num int64) {
res := ifaceWindowsRe.FindStringSubmatch(name)
if len(res) > 1 {
iface = res[1]
}
if len(res) > 2 {
num, _ = strconv.ParseInt(res[2], 10, 32)
@ -70,42 +197,62 @@ func parseInterfaceName(name string) (prefix string, bus int, num int64) {
return
}
func (i InterfacesAddrs) SortWithPriority(priority []string) {
less := func(a, b net.Interface) bool {
aPrefix, aBus, aNum := parseInterfaceName(a.Name)
bPrefix, bBus, bNum := parseInterfaceName(b.Name)
type interfaceComparer struct {
priority []string
}
aPrioirity := slice.FindPos(priority, aPrefix)
bPrioirity := slice.FindPos(priority, bPrefix)
func (i interfaceComparer) Compare(a, b string) int {
aPrefix, aType, aBus, aNum := parseInterfaceName(a)
bPrefix, bType, bBus, bNum := parseInterfaceName(b)
if aPrefix == bPrefix {
return aNum < bNum
} else if aPrioirity == -1 && bPrioirity == -1 {
// sort alphabetically
return aPrefix < bPrefix
} else if aPrioirity != -1 && bPrioirity != -1 {
// in case we have [eth, wlan]
if aPrioirity == bPrioirity {
// prioritize eth0 over wlan0
return aPrioirity < bPrioirity
aPrioirity := slice.FindPos(i.priority, aPrefix)
bPrioirity := slice.FindPos(i.priority, bPrefix)
if aPrioirity != -1 && bPrioirity != -1 || aPrioirity == -1 && bPrioirity == -1 {
if aPrefix != bPrefix {
if aPrioirity != -1 && bPrioirity != -1 {
// prioritize by priority
return cmp.Compare(aPrioirity, bPrioirity)
} else {
// prioritize by prefix
return cmp.Compare(aPrefix, bPrefix)
}
// prioritise wlan1 over eth8
if aBus != bBus {
return aBus < bBus
}
return aNum < bNum
} else if aPrioirity != -1 {
return true
} else {
return false
}
if aType != bType {
return cmp.Compare(aType.Priority(), bType.Priority())
}
if aBus != bBus {
return cmp.Compare(aBus, bBus)
}
if aNum != bNum {
return cmp.Compare(aNum, bNum)
}
// shouldn't be a case
return cmp.Compare(a, b)
}
slices.SortFunc(i.Interfaces, func(a, b net.Interface) int {
if less(a, b) {
return -1
}
if aPrioirity == -1 {
return 1
})
} else {
return -1
}
}
func (i InterfacesAddrs) SortInterfacesWithPriority(priority []string) {
sorter := interfaceComparer{priority: priority}
compare := func(a, b NetInterfaceWithAddrCache) int {
return sorter.Compare(a.Name, b.Name)
}
slices.SortFunc(i.Interfaces, compare)
}
func (i InterfacesAddrs) NetInterfaces() []net.Interface {
var s = make([]net.Interface, 0, len(i.Interfaces))
for _, iface := range i.Interfaces {
s = append(s, iface.Interface)
}
return s
}
func getStrings(i InterfacesAddrs) (allStrings []string) {
@ -118,3 +265,65 @@ func getStrings(i InterfacesAddrs) (allStrings []string) {
slices.Sort(allStrings)
return
}
func (i InterfacesAddrs) GetInterfaceByAddr(addr net.Addr) (net.Interface, bool) {
for _, iface := range i.Interfaces {
for _, addrInIface := range iface.GetAddr() {
if addr.String() == addrInIface.String() {
return iface.Interface, true
}
}
}
return net.Interface{}, false
}
// SortIPsLikeInterfaces sort IPs in a way they match sorted interface addresses(via mask matching)
// e.g. we have interfaces
// - en0: 192.168.1.10/24
// - lo0: 127.0.0.1/8
// we pass IPs: 10.124.22.1, 127.0.0.1, 192.168.1.25
// we will get: 192.168.1.25, 127.0.0.1, 10.124.22.1
// 10.124.22.1 does not match any interface, so it will be at the end
func (i InterfacesAddrs) SortIPsLikeInterfaces(ips []net.IP) {
slices.SortFunc(ips, func(a, b net.IP) int {
posA, _ := i.findInterfacePosByIP(a)
posB, _ := i.findInterfacePosByIP(b)
if posA == -1 && posB != -1 {
return 1
}
if posA != -1 && posB == -1 {
return -1
}
if posA < posB {
return -1
} else if posA > posB {
return 1
}
return 0
})
}
func (i InterfacesAddrs) findInterfacePosByIP(ip net.IP) (pos int, equal bool) {
for position, iface := range i.Interfaces {
for _, addr := range iface.GetAddr() {
if ni, ok := addr.(*net.IPNet); ok {
if ni.Contains(ip) {
return position, ni.IP.Equal(ip)
}
}
}
}
return -1, false
}
func filterInterfaces(ifaces []NetInterfaceWithAddrCache) []NetInterfaceWithAddrCache {
return slice.Filter(ifaces, func(iface NetInterfaceWithAddrCache) bool {
if iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagMulticast != 0 && iface.Flags&net.FlagLoopback == 0 {
if len(iface.GetAddr()) > 0 {
return true
}
}
return false
})
}

View file

@ -1,6 +1,11 @@
package addrs
import "testing"
import (
"sort"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_parseInterfaceName(t *testing.T) {
type args struct {
@ -10,18 +15,27 @@ func Test_parseInterfaceName(t *testing.T) {
name string
args args
wantPrefix string
wantBus int
wantType NamingType
wantBus int64
wantNum int64
}{
{"eth0", args{"eth0"}, "eth", 0, 0},
{"eth1", args{"eth1"}, "eth", 0, 1},
{"eth10", args{"eth10"}, "eth", 0, 10},
{"enp0s10", args{"enp0s10"}, "en", 0, 16},
{"wlp0s20f3", args{"wlp0s20f3"}, "wl", 0, 8435},
{"eth0", args{"eth0"}, "eth", NamingTypeOld, 0, 0},
{"eth1", args{"eth1"}, "eth", NamingTypeOld, 0, 1},
{"eth10", args{"eth10"}, "eth", NamingTypeOld, 0, 10},
{"enp0s10", args{"enp0s10"}, "en", NamingTypeBusSlot, 0, 0x10},
{"wlp0s20f3", args{"wlp0s20f3"}, "wl", NamingTypeBusSlot, 0, 0x20f3},
{"tun0", args{"tun0"}, "tun", NamingTypeOld, 0, 0},
{"tap0", args{"tap0"}, "tap", NamingTypeOld, 0, 0},
{"lo0", args{"lo0"}, "lo", NamingTypeOld, 0, 0},
{"lo1", args{"lo1"}, "lo", NamingTypeOld, 0, 1},
{"lo10", args{"lo10"}, "lo", NamingTypeOld, 0, 10},
{"wlx001122334455", args{"wlx001122334455"}, "wl", NamingTypeMac, 0x001122334455, 0},
{"wlxffffffffffff", args{"wlxffffffffffff"}, "wl", NamingTypeMac, 0xffffffffffff, 0},
{"eno16777736", args{"eno16777736"}, "en", NamingTypeOnboard, 0x16777736, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotPrefix, gotBus, gotNum := parseInterfaceName(tt.args.name)
gotPrefix, gotType, gotBus, gotNum := parseInterfaceName(tt.args.name)
if gotPrefix != tt.wantPrefix {
t.Errorf("parseInterfaceName() gotPrefix = %v, want %v", gotPrefix, tt.wantPrefix)
}
@ -31,6 +45,54 @@ func Test_parseInterfaceName(t *testing.T) {
if gotNum != tt.wantNum {
t.Errorf("parseInterfaceName() gotNum = %v, want %v", gotNum, tt.wantNum)
}
if gotType != tt.wantType {
t.Errorf("parseInterfaceName() gotType = %v, want %v", gotType, tt.wantType)
}
})
}
}
// TestInterfaceSorterSorting tests sorting a list of interface names using the Compare method.
func TestInterfaceSorterSorting(t *testing.T) {
sorter := interfaceComparer{
priority: []string{"wl", "wlan", "en", "eth", "tun", "tap", "utun"},
}
// List of interfaces to sort
interfaces := []string{
"tap0",
"awdl0",
"eth0",
"eno1",
"wlp2s0",
"ens2",
"enp0s3",
"tun0",
"wlan0",
"enx001122334455",
"wlx001122334455",
}
// Expected order after sorting
expected := []string{
"wlp2s0", // Wireless LAN on PCI bus
"wlx001122334455", // Wireless LAN with MAC address
"wlan0", // Old-style Wireless LAN
"eno1", // Highest priority (onboard Ethernet)
"enp0s3", // PCI bus Ethernet
"enx001122334455", // Ethernet with MAC address
"ens2", // Hotplug Ethernet
"eth0", // Old-style Ethernet
"tun0", // VPN TUN interface
"tap0", // VPN TAP interface
"awdl0",
}
// Sorting the interfaces using the Compare method
sort.Slice(interfaces, func(i, j int) bool {
return sorter.Compare(interfaces[i], interfaces[j]) < 0
})
// Assert the sorted order matches the expected order
assert.Equal(t, expected, interfaces, "The interfaces should be sorted correctly according to priority.")
}

View file

@ -6,8 +6,6 @@ package addrs
import (
"net"
"slices"
"github.com/anyproto/anytype-heart/util/slice"
)
func SetInterfaceAddrsGetter(getter InterfaceAddrsGetter) {}
@ -32,11 +30,7 @@ func GetInterfacesAddrs() (iAddrs InterfacesAddrs, err error) {
if err != nil {
return
}
iAddrs.Interfaces = ifaces
iAddrs.Interfaces = slice.Filter(iAddrs.Interfaces, func(iface net.Interface) bool {
return iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagMulticast != 0
})
iAddrs.Interfaces = filterInterfaces(WrapInterfaces(ifaces))
return
}

View file

@ -57,8 +57,9 @@ func GetInterfacesAddrs() (addrs InterfacesAddrs, err error) {
}
lock.Unlock()
for _, iface := range interfaceGetter.Interfaces() {
addrs.Interfaces = append(addrs.Interfaces, iface.Interface)
ifaceWrapped := WrapInterface(iface.Interface)
unmaskedAddrs := iface.Addrs
ifaceAddrs := make([]net.Addr, 0, len(unmaskedAddrs))
for _, addr := range unmaskedAddrs {
var mask []byte
if len(addr.Ip) == 4 {
@ -66,11 +67,17 @@ func GetInterfacesAddrs() (addrs InterfacesAddrs, err error) {
} else {
mask = ipV6MaskFromPrefix(addr.Prefix)
}
addrs.Addrs = append(addrs.Addrs, &net.IPNet{
ifaceAddrs = append(ifaceAddrs, &net.IPNet{
IP: addr.Ip,
Mask: mask,
})
}
// inject cached addresses, because we can't get them from net.Interface's Addrs() on android
ifaceWrapped.cachedAddrs = ifaceAddrs
addrs.Addrs = append(addrs.Addrs, ifaceAddrs...)
addrs.Interfaces = append(addrs.Interfaces, ifaceWrapped)
}
addrs.Interfaces = filterInterfaces(addrs.Interfaces)
return
}

File diff suppressed because it is too large Load diff

View file

@ -6405,6 +6405,7 @@ message Rpc {
message AccountSelectTrace {
message Request {
option (no_auth) = true;
string dir = 1; // empty means using OS-provided temp dir
}
message Response {

View file

@ -23,10 +23,10 @@ import (
"github.com/anyproto/anytype-heart/space/spacecore/clientserver"
)
var interfacesSortPriority = []string{"en", "wlan", "wl", "eth", "lo"}
type Hook int
var interfacesSortPriority = []string{"wlan", "wl", "en", "eth", "tun", "tap", "utun", "lo"}
const (
PeerToPeerImpossible Hook = 0
PeerToPeerPossible Hook = 1
@ -70,7 +70,7 @@ func (l *localDiscovery) Init(a *app.App) (err error) {
l.manualStart = a.MustComponent(config.CName).(*config.Config).DontStartLocalNetworkSyncAutomatically
l.nodeConf = a.MustComponent(config.CName).(*config.Config).GetNodeConf()
l.peerId = a.MustComponent(accountservice.CName).(accountservice.Service).Account().PeerId
l.periodicCheck = periodicsync.NewPeriodicSync(10, 0, l.checkAddrs, log)
l.periodicCheck = periodicsync.NewPeriodicSync(5, 0, l.checkAddrs, log)
l.drpcServer = app.MustComponent[clientserver.ClientServer](a)
return
}
@ -158,10 +158,11 @@ func (l *localDiscovery) checkAddrs(ctx context.Context) (err error) {
newAddrs, err := addrs.GetInterfacesAddrs()
l.notifyPeerToPeerStatus(newAddrs)
if err != nil {
return
return fmt.Errorf("getting iface addresses: %w", err)
}
newAddrs.SortWithPriority(interfacesSortPriority)
newAddrs.SortInterfacesWithPriority(interfacesSortPriority)
if newAddrs.Equal(l.interfacesAddrs) && l.server != nil {
return
}
@ -174,22 +175,45 @@ func (l *localDiscovery) checkAddrs(ctx context.Context) (err error) {
}
l.ctx, l.cancel = context.WithCancel(ctx)
if err = l.startServer(); err != nil {
return
return fmt.Errorf("starting mdns server: %w", err)
}
l.startQuerying(l.ctx)
return
}
func (l *localDiscovery) getAddresses() (ipv4, ipv6 []gonet.IP) {
for _, iface := range l.interfacesAddrs.Interfaces {
for _, addr := range iface.GetAddr() {
ip := addr.(*gonet.IPNet).IP
if ip.To4() != nil {
ipv4 = append(ipv4, ip)
} else {
ipv6 = append(ipv6, ip)
}
}
}
if len(ipv4) == 0 {
// fallback in case we have no ipv4 addresses from interfaces
for _, addr := range l.interfacesAddrs.Addrs {
ip := strings.Split(addr.String(), "/")[0]
ipVal := gonet.ParseIP(ip)
if ipVal.To4() != nil {
ipv4 = append(ipv4, ipVal)
} else {
ipv6 = append(ipv6, ipVal)
}
}
l.interfacesAddrs.SortIPsLikeInterfaces(ipv4)
}
return
}
func (l *localDiscovery) startServer() (err error) {
l.ipv4 = l.ipv4[:0]
l.ipv6 = l.ipv6[:0]
for _, addr := range l.interfacesAddrs.Addrs {
ip := strings.Split(addr.String(), "/")[0]
if gonet.ParseIP(ip).To4() != nil {
l.ipv4 = append(l.ipv4, ip)
} else {
l.ipv6 = append(l.ipv6, ip)
}
ipv4, _ := l.getAddresses() // ignore ipv6 for now
for _, ip := range ipv4 {
l.ipv4 = append(l.ipv4, ip.String())
}
log.Debug("starting mdns server", zap.Strings("ips", l.ipv4), zap.Int("port", l.port), zap.String("peerId", l.peerId))
l.server, err = zeroconf.RegisterProxy(
@ -200,7 +224,7 @@ func (l *localDiscovery) startServer() (err error) {
l.peerId,
l.ipv4, // do not include ipv6 addresses, because they are disabled
nil,
l.interfacesAddrs.Interfaces,
l.interfacesAddrs.NetInterfaces(),
zeroconf.TTL(60),
zeroconf.ServerSelectIPTraffic(zeroconf.IPv4), // disable ipv6 for now
zeroconf.WriteTimeout(time.Second*1),
@ -223,6 +247,7 @@ func (l *localDiscovery) readAnswers(ch chan *zeroconf.ServiceEntry) {
continue
}
var portAddrs []string
l.interfacesAddrs.SortIPsLikeInterfaces(entry.AddrIPv4)
for _, a := range entry.AddrIPv4 {
portAddrs = append(portAddrs, fmt.Sprintf("%s:%d", a.String(), entry.Port))
}
@ -248,10 +273,10 @@ func (l *localDiscovery) browse(ctx context.Context, ch chan *zeroconf.ServiceEn
if err != nil {
return
}
newAddrs.SortWithPriority(interfacesSortPriority)
newAddrs.SortInterfacesWithPriority(interfacesSortPriority)
if err := zeroconf.Browse(ctx, serviceName, mdnsDomain, ch,
zeroconf.ClientWriteTimeout(time.Second*1),
zeroconf.SelectIfaces(newAddrs.Interfaces),
zeroconf.SelectIfaces(newAddrs.NetInterfaces()),
zeroconf.SelectIPTraffic(zeroconf.IPv4)); err != nil {
log.Error("browsing failed", zap.Error(err))
}
@ -266,7 +291,7 @@ func (l *localDiscovery) notifyPeerToPeerStatus(newAddrs addrs.InterfacesAddrs)
}
func (l *localDiscovery) notifyP2PNotPossible(newAddrs addrs.InterfacesAddrs) bool {
return len(newAddrs.Interfaces) == 0 || addrs.IsLoopBack(newAddrs.Interfaces)
return len(newAddrs.Interfaces) == 0 || addrs.IsLoopBack(newAddrs.NetInterfaces())
}
func (l *localDiscovery) executeHook(hook Hook) {

View file

@ -160,7 +160,7 @@ func (l *localDiscovery) notifyPeerToPeerStatus(newAddrs addrs.InterfacesAddrs)
}
func (l *localDiscovery) notifyP2PNotPossible(newAddrs addrs.InterfacesAddrs) bool {
return len(newAddrs.Interfaces) == 0 || IsLoopBack(newAddrs.Interfaces)
return len(newAddrs.Interfaces) == 0 || IsLoopBack(newAddrs.NetInterfaces())
}
func IsLoopBack(interfaces []net.Interface) bool {

View file

@ -3,11 +3,13 @@ package spacecore
import (
"context"
"fmt"
"net/url"
"github.com/anyproto/any-sync/commonspace"
"github.com/anyproto/any-sync/commonspace/spacesyncproto"
"github.com/anyproto/any-sync/net/peer"
"go.uber.org/zap"
"golang.org/x/exp/slices"
"github.com/anyproto/anytype-heart/space/spacecore/clientspaceproto"
)
@ -49,8 +51,21 @@ func (r *rpcHandler) SpaceExchange(ctx context.Context, request *clientspaceprot
return nil, err
}
var portAddrs []string
peerAddr := peer.CtxPeerAddr(ctx)
if peerAddr != "" {
// prioritize address remote peer connected us from
if u, errParse := url.Parse(peerAddr); errParse == nil {
portAddrs = append(portAddrs, u.Host)
}
}
for _, ip := range request.LocalServer.Ips {
portAddrs = append(portAddrs, fmt.Sprintf("%s:%d", ip, request.LocalServer.Port))
addr := fmt.Sprintf("%s:%d", ip, request.LocalServer.Port)
if slices.Contains(portAddrs, addr) {
continue
}
portAddrs = append(portAddrs, addr)
}
r.s.peerService.SetPeerAddrs(peerId, portAddrs)
r.s.peerStore.UpdateLocalPeer(peerId, request.SpaceIds)