mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-09 14:50:56 +00:00
Check relays for available devices
This commit is contained in:
parent
27465353c1
commit
a388fb0bb7
@ -16,9 +16,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/protocol"
|
||||
|
||||
"github.com/syncthing/relaysrv/client"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/model"
|
||||
|
||||
"github.com/thejerf/suture"
|
||||
)
|
||||
|
||||
@ -40,6 +43,8 @@ type connectionSvc struct {
|
||||
tlsCfg *tls.Config
|
||||
conns chan intermediateConnection
|
||||
|
||||
lastRelayCheck map[protocol.DeviceID]time.Time
|
||||
|
||||
mut sync.RWMutex
|
||||
connType map[protocol.DeviceID]model.ConnectionType
|
||||
}
|
||||
@ -58,7 +63,8 @@ func newConnectionSvc(cfg *config.Wrapper, myID protocol.DeviceID, mdl *model.Mo
|
||||
tlsCfg: tlsCfg,
|
||||
conns: make(chan intermediateConnection),
|
||||
|
||||
connType: make(map[protocol.DeviceID]model.ConnectionType),
|
||||
connType: make(map[protocol.DeviceID]model.ConnectionType),
|
||||
lastRelayCheck: make(map[protocol.DeviceID]time.Time),
|
||||
}
|
||||
cfg.Subscribe(svc)
|
||||
|
||||
@ -135,13 +141,23 @@ next:
|
||||
continue
|
||||
}
|
||||
|
||||
// We should not already be connected to the other party. TODO: This
|
||||
// could use some better handling. If the old connection is dead but
|
||||
// hasn't timed out yet we may want to drop *that* connection and keep
|
||||
// this one. But in case we are two devices connecting to each other
|
||||
// in parallel we don't want to do that or we end up with no
|
||||
// connections still established...
|
||||
if s.model.ConnectedTo(remoteID) {
|
||||
// If we have a relay connection, and the new incoming connection is
|
||||
// not a relay connection, we should drop that, and prefer the this one.
|
||||
s.mut.RLock()
|
||||
ct, ok := s.connType[remoteID]
|
||||
s.mut.RUnlock()
|
||||
if ok && !ct.IsDirect() && c.connType.IsDirect() {
|
||||
if debugNet {
|
||||
l.Debugln("Switching connections", remoteID)
|
||||
}
|
||||
s.model.Close(remoteID, fmt.Errorf("switching connections"))
|
||||
} else if s.model.ConnectedTo(remoteID) {
|
||||
// We should not already be connected to the other party. TODO: This
|
||||
// could use some better handling. If the old connection is dead but
|
||||
// hasn't timed out yet we may want to drop *that* connection and keep
|
||||
// this one. But in case we are two devices connecting to each other
|
||||
// in parallel we don't want to do that or we end up with no
|
||||
// connections still established...
|
||||
l.Infof("Connected to already connected device (%s)", remoteID)
|
||||
c.conn.Close()
|
||||
continue
|
||||
@ -224,15 +240,22 @@ func (s *connectionSvc) connect() {
|
||||
continue
|
||||
}
|
||||
|
||||
if s.model.ConnectedTo(deviceID) {
|
||||
connected := s.model.ConnectedTo(deviceID)
|
||||
|
||||
s.mut.RLock()
|
||||
ct, ok := s.connType[deviceID]
|
||||
s.mut.RUnlock()
|
||||
if connected && ok && ct.IsDirect() {
|
||||
continue
|
||||
}
|
||||
|
||||
var addrs []string
|
||||
var relays []string
|
||||
for _, addr := range deviceCfg.Addresses {
|
||||
if addr == "dynamic" {
|
||||
if discoverer != nil {
|
||||
t, _ := discoverer.Lookup(deviceID)
|
||||
t, r := discoverer.Lookup(deviceID)
|
||||
relays = append(relays, r...)
|
||||
if len(t) == 0 {
|
||||
continue
|
||||
}
|
||||
@ -267,11 +290,83 @@ func (s *connectionSvc) connect() {
|
||||
continue
|
||||
}
|
||||
|
||||
if connected {
|
||||
s.model.Close(deviceID, fmt.Errorf("switching connections"))
|
||||
}
|
||||
|
||||
s.conns <- intermediateConnection{
|
||||
conn, model.ConnectionTypeBasicDial,
|
||||
}
|
||||
continue nextDevice
|
||||
}
|
||||
|
||||
// Only connect via relays if not already connected
|
||||
// Also, do not set lastRelayCheck time if we have no relays,
|
||||
// as otherwise when we do discover relays, we might have to
|
||||
// wait up to RelayReconnectIntervalM to connect again.
|
||||
if connected || len(relays) == 0 {
|
||||
continue nextDevice
|
||||
}
|
||||
|
||||
reconIntv := time.Duration(s.cfg.Options().RelayReconnectIntervalM) * time.Minute
|
||||
if last, ok := s.lastRelayCheck[deviceID]; ok && time.Since(last) < reconIntv {
|
||||
if debugNet {
|
||||
l.Debugln("Skipping connecting via relay to", deviceID, "last checked at", last)
|
||||
}
|
||||
continue nextDevice
|
||||
} else if debugNet {
|
||||
l.Debugln("Trying relay connections to", deviceID, relays)
|
||||
}
|
||||
|
||||
s.lastRelayCheck[deviceID] = time.Now()
|
||||
|
||||
for _, addr := range relays {
|
||||
uri, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
l.Infoln("Failed to parse relay connection url:", addr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
inv, err := client.GetInvitationFromRelay(uri, deviceID, s.tlsCfg.Certificates)
|
||||
if err != nil {
|
||||
if debugNet {
|
||||
l.Debugf("Failed to get invitation for %s from %s: %v", deviceID, uri, err)
|
||||
}
|
||||
continue
|
||||
} else if debugNet {
|
||||
l.Debugln("Succesfully retrieved relay invitation", inv, "from", uri)
|
||||
}
|
||||
|
||||
conn, err := client.JoinSession(inv)
|
||||
if err != nil {
|
||||
if debugNet {
|
||||
l.Debugf("Failed to join relay session %s: %v", inv, err)
|
||||
}
|
||||
continue
|
||||
} else if debugNet {
|
||||
l.Debugln("Sucessfully joined relay session", inv)
|
||||
}
|
||||
|
||||
setTCPOptions(conn.(*net.TCPConn))
|
||||
|
||||
var tc *tls.Conn
|
||||
|
||||
if inv.ServerSocket {
|
||||
tc = tls.Server(conn, s.tlsCfg)
|
||||
} else {
|
||||
tc = tls.Client(conn, s.tlsCfg)
|
||||
}
|
||||
err = tc.Handshake()
|
||||
if err != nil {
|
||||
l.Infof("TLS handshake (BEP/relay %s): %v", inv, err)
|
||||
tc.Close()
|
||||
continue
|
||||
}
|
||||
s.conns <- intermediateConnection{
|
||||
tc, model.ConnectionTypeRelayDial,
|
||||
}
|
||||
continue nextDevice
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(delay)
|
||||
|
@ -223,6 +223,7 @@ type OptionsConfiguration struct {
|
||||
MaxSendKbps int `xml:"maxSendKbps" json:"maxSendKbps"`
|
||||
MaxRecvKbps int `xml:"maxRecvKbps" json:"maxRecvKbps"`
|
||||
ReconnectIntervalS int `xml:"reconnectionIntervalS" json:"reconnectionIntervalS" default:"60"`
|
||||
RelayReconnectIntervalM int `xml:"relayReconnectIntervalM" json:"relayReconnectIntervalM" default:"10"`
|
||||
StartBrowser bool `xml:"startBrowser" json:"startBrowser" default:"true"`
|
||||
UPnPEnabled bool `xml:"upnpEnabled" json:"upnpEnabled" default:"true"`
|
||||
UPnPLeaseM int `xml:"upnpLeaseMinutes" json:"upnpLeaseMinutes" default:"60"`
|
||||
|
@ -40,6 +40,7 @@ func TestDefaultValues(t *testing.T) {
|
||||
MaxSendKbps: 0,
|
||||
MaxRecvKbps: 0,
|
||||
ReconnectIntervalS: 60,
|
||||
RelayReconnectIntervalM: 10,
|
||||
StartBrowser: true,
|
||||
UPnPEnabled: true,
|
||||
UPnPLeaseM: 60,
|
||||
@ -152,6 +153,7 @@ func TestOverriddenValues(t *testing.T) {
|
||||
MaxSendKbps: 1234,
|
||||
MaxRecvKbps: 2341,
|
||||
ReconnectIntervalS: 6000,
|
||||
RelayReconnectIntervalM: 20,
|
||||
StartBrowser: false,
|
||||
UPnPEnabled: false,
|
||||
UPnPLeaseM: 90,
|
||||
|
1
lib/config/testdata/overridenvalues.xml
vendored
1
lib/config/testdata/overridenvalues.xml
vendored
@ -13,6 +13,7 @@
|
||||
<maxSendKbps>1234</maxSendKbps>
|
||||
<maxRecvKbps>2341</maxRecvKbps>
|
||||
<reconnectionIntervalS>6000</reconnectionIntervalS>
|
||||
<relayReconnectIntervalM>20</relayReconnectIntervalM>
|
||||
<startBrowser>false</startBrowser>
|
||||
<upnpEnabled>false</upnpEnabled>
|
||||
<upnpLeaseMinutes>90</upnpLeaseMinutes>
|
||||
|
Loading…
Reference in New Issue
Block a user