From 431d51f5c49ed7860e289ddab3c1fcf30004ff00 Mon Sep 17 00:00:00 2001 From: Audrius Butkevicius Date: Mon, 23 Nov 2015 21:14:46 +0000 Subject: [PATCH] Add timeouts to relay methods --- lib/connections/connections.go | 2 +- lib/relay/client/client.go | 6 +++--- lib/relay/client/dynamic.go | 6 ++++-- lib/relay/client/methods.go | 10 +++++----- lib/relay/client/static.go | 14 ++++++++------ lib/relay/relay.go | 2 +- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/connections/connections.go b/lib/connections/connections.go index 3852d829e..740d48689 100644 --- a/lib/connections/connections.go +++ b/lib/connections/connections.go @@ -377,7 +377,7 @@ func (s *connectionSvc) connectViaRelay(deviceID protocol.DeviceID, addr discove return nil } - inv, err := client.GetInvitationFromRelay(uri, deviceID, s.tlsCfg.Certificates) + inv, err := client.GetInvitationFromRelay(uri, deviceID, s.tlsCfg.Certificates, 10*time.Second) if err != nil { l.Debugf("Failed to get invitation for %s from %s: %v", deviceID, uri, err) return nil diff --git a/lib/relay/client/client.go b/lib/relay/client/client.go index 2dee8c6ae..992218ed9 100644 --- a/lib/relay/client/client.go +++ b/lib/relay/client/client.go @@ -11,7 +11,7 @@ import ( "github.com/syncthing/syncthing/lib/relay/protocol" ) -type relayClientFactory func(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) RelayClient +type relayClientFactory func(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation, timeout time.Duration) RelayClient var ( supportedSchemes = map[string]relayClientFactory{ @@ -31,11 +31,11 @@ type RelayClient interface { URI() *url.URL } -func NewClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) (RelayClient, error) { +func NewClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation, timeout time.Duration) (RelayClient, error) { factory, ok := supportedSchemes[uri.Scheme] if !ok { return nil, fmt.Errorf("Unsupported scheme: %s", uri.Scheme) } - return factory(uri, certs, invitations), nil + return factory(uri, certs, invitations, timeout), nil } diff --git a/lib/relay/client/dynamic.go b/lib/relay/client/dynamic.go index 3e3dc4e46..13017793a 100644 --- a/lib/relay/client/dynamic.go +++ b/lib/relay/client/dynamic.go @@ -22,13 +22,14 @@ type dynamicClient struct { certs []tls.Certificate invitations chan protocol.SessionInvitation closeInvitationsOnFinish bool + timeout time.Duration mut sync.RWMutex client RelayClient stop chan struct{} } -func newDynamicClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) RelayClient { +func newDynamicClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation, timeout time.Duration) RelayClient { closeInvitationsOnFinish := false if invitations == nil { closeInvitationsOnFinish = true @@ -39,6 +40,7 @@ func newDynamicClient(uri *url.URL, certs []tls.Certificate, invitations chan pr certs: certs, invitations: invitations, closeInvitationsOnFinish: closeInvitationsOnFinish, + timeout: timeout, mut: sync.NewRWMutex(), } @@ -94,7 +96,7 @@ func (c *dynamicClient) Serve() { l.Debugln(c, "skipping relay", addr, err) continue } - client, err := NewClient(ruri, c.certs, c.invitations) + client, err := NewClient(ruri, c.certs, c.invitations, c.timeout) if err != nil { continue } diff --git a/lib/relay/client/methods.go b/lib/relay/client/methods.go index c4984e36f..831118b3d 100644 --- a/lib/relay/client/methods.go +++ b/lib/relay/client/methods.go @@ -16,7 +16,7 @@ import ( "github.com/syncthing/syncthing/lib/relay/protocol" ) -func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs []tls.Certificate) (protocol.SessionInvitation, error) { +func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs []tls.Certificate, timeout time.Duration) (protocol.SessionInvitation, error) { if uri.Scheme != "relay" { return protocol.SessionInvitation{}, fmt.Errorf("Unsupported relay scheme: %v", uri.Scheme) } @@ -27,7 +27,7 @@ func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs [ } conn := tls.Client(rconn, configForCerts(certs)) - conn.SetDeadline(time.Now().Add(10 * time.Second)) + conn.SetDeadline(time.Now().Add(timeout)) if err := performHandshakeAndValidation(conn, uri); err != nil { return protocol.SessionInvitation{}, err @@ -99,10 +99,10 @@ func JoinSession(invitation protocol.SessionInvitation) (net.Conn, error) { } } -func TestRelay(uri *url.URL, certs []tls.Certificate, sleep time.Duration, times int) bool { +func TestRelay(uri *url.URL, certs []tls.Certificate, sleep, timeout time.Duration, times int) bool { id := syncthingprotocol.NewDeviceID(certs[0].Certificate[0]) invs := make(chan protocol.SessionInvitation, 1) - c, err := NewClient(uri, certs, invs) + c, err := NewClient(uri, certs, invs, timeout) if err != nil { close(invs) return false @@ -114,7 +114,7 @@ func TestRelay(uri *url.URL, certs []tls.Certificate, sleep time.Duration, times }() for i := 0; i < times; i++ { - _, err := GetInvitationFromRelay(uri, id, certs) + _, err := GetInvitationFromRelay(uri, id, certs, timeout) if err == nil { return true } diff --git a/lib/relay/client/static.go b/lib/relay/client/static.go index 19624e476..26fd70cfb 100644 --- a/lib/relay/client/static.go +++ b/lib/relay/client/static.go @@ -22,7 +22,8 @@ type staticClient struct { config *tls.Config - timeout time.Duration + messageTimeout time.Duration + connectTimeout time.Duration stop chan struct{} stopped chan struct{} @@ -34,7 +35,7 @@ type staticClient struct { latency time.Duration } -func newStaticClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation) RelayClient { +func newStaticClient(uri *url.URL, certs []tls.Certificate, invitations chan protocol.SessionInvitation, timeout time.Duration) RelayClient { closeInvitationsOnFinish := false if invitations == nil { closeInvitationsOnFinish = true @@ -49,7 +50,8 @@ func newStaticClient(uri *url.URL, certs []tls.Certificate, invitations chan pro config: configForCerts(certs), - timeout: time.Minute * 2, + messageTimeout: time.Minute * 2, + connectTimeout: timeout, stop: make(chan struct{}), stopped: make(chan struct{}), @@ -95,12 +97,12 @@ func (c *staticClient) Serve() { go messageReader(c.conn, messages, errors) - timeout := time.NewTimer(c.timeout) + timeout := time.NewTimer(c.messageTimeout) for { select { case message := <-messages: - timeout.Reset(c.timeout) + timeout.Reset(c.messageTimeout) l.Debugf("%s received message %T", c, message) switch msg := message.(type) { @@ -201,7 +203,7 @@ func (c *staticClient) connect() error { return err } - if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil { + if err := conn.SetDeadline(time.Now().Add(c.connectTimeout)); err != nil { conn.Close() return err } diff --git a/lib/relay/relay.go b/lib/relay/relay.go index c156d8809..7bf538f92 100644 --- a/lib/relay/relay.go +++ b/lib/relay/relay.go @@ -110,7 +110,7 @@ func (s *Svc) CommitConfiguration(from, to config.Configuration) bool { _, ok := s.tokens[key] if !ok { l.Debugln("Connecting to relay", uri) - c, err := client.NewClient(uri, s.tlsCfg.Certificates, s.invitations) + c, err := client.NewClient(uri, s.tlsCfg.Certificates, s.invitations, 10*time.Second) if err != nil { l.Debugln("Failed to connect to relay", uri, err) continue