Merge pull request #134 from kradalby/loop-97

This commit is contained in:
Kristoffer Dalby 2021-10-02 23:13:41 +01:00 committed by GitHub
commit 63fa475913
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 22 deletions

25
app.go
View file

@ -172,16 +172,18 @@ func (h *Headscale) Serve() error {
r.GET("/apple/:platform", h.ApplePlatformConfig) r.GET("/apple/:platform", h.ApplePlatformConfig)
var err error var err error
timeout := 30 * time.Second
go h.watchForKVUpdates(5000) go h.watchForKVUpdates(5000)
go h.expireEphemeralNodes(5000) go h.expireEphemeralNodes(5000)
s := &http.Server{ s := &http.Server{
Addr: h.cfg.Addr, Addr: h.cfg.Addr,
Handler: r, Handler: r,
ReadTimeout: timeout, ReadTimeout: 30 * time.Second,
WriteTimeout: timeout, // Go does not handle timeouts in HTTP very well, and there is
// no good way to handle streaming timeouts, therefore we need to
// keep this at unlimited and be careful to clean up connections
// https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/#aboutstreaming
WriteTimeout: 0,
} }
if h.cfg.TLSLetsEncryptHostname != "" { if h.cfg.TLSLetsEncryptHostname != "" {
@ -194,13 +196,9 @@ func (h *Headscale) Serve() error {
HostPolicy: autocert.HostWhitelist(h.cfg.TLSLetsEncryptHostname), HostPolicy: autocert.HostWhitelist(h.cfg.TLSLetsEncryptHostname),
Cache: autocert.DirCache(h.cfg.TLSLetsEncryptCacheDir), Cache: autocert.DirCache(h.cfg.TLSLetsEncryptCacheDir),
} }
s := &http.Server{
Addr: h.cfg.Addr, s.TLSConfig = m.TLSConfig()
TLSConfig: m.TLSConfig(),
Handler: r,
ReadTimeout: timeout,
WriteTimeout: timeout,
}
if h.cfg.TLSLetsEncryptChallengeType == "TLS-ALPN-01" { if h.cfg.TLSLetsEncryptChallengeType == "TLS-ALPN-01" {
// Configuration via autocert with TLS-ALPN-01 (https://tools.ietf.org/html/rfc8737) // Configuration via autocert with TLS-ALPN-01 (https://tools.ietf.org/html/rfc8737)
// The RFC requires that the validation is done on port 443; in other words, headscale // The RFC requires that the validation is done on port 443; in other words, headscale
@ -211,7 +209,6 @@ func (h *Headscale) Serve() error {
// port 80 for the certificate validation in addition to the headscale // port 80 for the certificate validation in addition to the headscale
// service, which can be configured to run on any other port. // service, which can be configured to run on any other port.
go func() { go func() {
log.Fatal(). log.Fatal().
Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, m.HTTPHandler(http.HandlerFunc(h.redirect)))). Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, m.HTTPHandler(http.HandlerFunc(h.redirect)))).
Msg("failed to set up a HTTP server") Msg("failed to set up a HTTP server")

View file

@ -433,7 +433,7 @@ func (s *IntegrationTestSuite) TestPingAllPeers() {
command := []string{ command := []string{
"tailscale", "ping", "tailscale", "ping",
"--timeout=1s", "--timeout=1s",
"--c=20", "--c=10",
"--until-direct=true", "--until-direct=true",
ip.String(), ip.String(),
} }

View file

@ -308,7 +308,8 @@ func (h *Headscale) notifyChangesToPeers(m *Machine) {
Str("func", "notifyChangesToPeers"). Str("func", "notifyChangesToPeers").
Str("machine", m.Name). Str("machine", m.Name).
Str("peer", p.Name). Str("peer", p.Name).
Msgf("Peer %s does not appear to be polling", p.Name) Msgf("Peer %s does not have an open update client, skipping.", p.Name)
continue
} }
log.Trace(). log.Trace().
Str("func", "notifyChangesToPeers"). Str("func", "notifyChangesToPeers").
@ -379,11 +380,12 @@ func (h *Headscale) sendRequestOnUpdateChannel(m *tailcfg.Node) error {
Msgf("Notified machine %s", m.Name) Msgf("Notified machine %s", m.Name)
} }
} else { } else {
err := errors.New("machine does not have an open update channel")
log.Info(). log.Info().
Str("func", "requestUpdate"). Str("func", "requestUpdate").
Str("machine", m.Name). Str("machine", m.Name).
Msgf("Machine %s does not appear to be polling", m.Name) Msgf("Machine %s does not have an open update channel", m.Name)
return errors.New("machine does not seem to be polling") return err
} }
return nil return nil
} }

31
poll.go
View file

@ -230,6 +230,7 @@ func (h *Headscale) PollNetMapStream(
Str("channel", "pollData"). Str("channel", "pollData").
Err(err). Err(err).
Msg("Cannot write data") Msg("Cannot write data")
return false
} }
log.Trace(). log.Trace().
Str("handler", "PollNetMapStream"). Str("handler", "PollNetMapStream").
@ -237,7 +238,7 @@ func (h *Headscale) PollNetMapStream(
Str("channel", "pollData"). Str("channel", "pollData").
Int("bytes", len(data)). Int("bytes", len(data)).
Msg("Data from pollData channel written successfully") Msg("Data from pollData channel written successfully")
// TODO: Abstract away all the database calls, this can cause race conditions // TODO(kradalby): Abstract away all the database calls, this can cause race conditions
// when an outdated machine object is kept alive, e.g. db is update from // when an outdated machine object is kept alive, e.g. db is update from
// command line, but then overwritten. // command line, but then overwritten.
err = h.UpdateMachine(&m) err = h.UpdateMachine(&m)
@ -258,7 +259,7 @@ func (h *Headscale) PollNetMapStream(
Str("machine", m.Name). Str("machine", m.Name).
Str("channel", "pollData"). Str("channel", "pollData").
Int("bytes", len(data)). Int("bytes", len(data)).
Msg("Machine updated successfully after sending pollData") Msg("Machine entry in database updated successfully after sending pollData")
return true return true
case data := <-keepAliveChan: case data := <-keepAliveChan:
@ -276,6 +277,7 @@ func (h *Headscale) PollNetMapStream(
Str("channel", "keepAlive"). Str("channel", "keepAlive").
Err(err). Err(err).
Msg("Cannot write keep alive message") Msg("Cannot write keep alive message")
return false
} }
log.Trace(). log.Trace().
Str("handler", "PollNetMapStream"). Str("handler", "PollNetMapStream").
@ -283,7 +285,7 @@ func (h *Headscale) PollNetMapStream(
Str("channel", "keepAlive"). Str("channel", "keepAlive").
Int("bytes", len(data)). Int("bytes", len(data)).
Msg("Keep alive sent successfully") Msg("Keep alive sent successfully")
// TODO: Abstract away all the database calls, this can cause race conditions // TODO(kradalby): Abstract away all the database calls, this can cause race conditions
// when an outdated machine object is kept alive, e.g. db is update from // when an outdated machine object is kept alive, e.g. db is update from
// command line, but then overwritten. // command line, but then overwritten.
err = h.UpdateMachine(&m) err = h.UpdateMachine(&m)
@ -336,6 +338,7 @@ func (h *Headscale) PollNetMapStream(
Str("channel", "update"). Str("channel", "update").
Err(err). Err(err).
Msg("Could not write the map response") Msg("Could not write the map response")
return false
} }
log.Trace(). log.Trace().
Str("handler", "PollNetMapStream"). Str("handler", "PollNetMapStream").
@ -347,7 +350,7 @@ func (h *Headscale) PollNetMapStream(
// we sometimes end in a state were the update // we sometimes end in a state were the update
// is not picked up by a client and we use this // is not picked up by a client and we use this
// to determine if we should "force" an update. // to determine if we should "force" an update.
// TODO: Abstract away all the database calls, this can cause race conditions // TODO(kradalby): Abstract away all the database calls, this can cause race conditions
// when an outdated machine object is kept alive, e.g. db is update from // when an outdated machine object is kept alive, e.g. db is update from
// command line, but then overwritten. // command line, but then overwritten.
err = h.UpdateMachine(&m) err = h.UpdateMachine(&m)
@ -393,13 +396,33 @@ func (h *Headscale) PollNetMapStream(
m.LastSeen = &now m.LastSeen = &now
h.db.Save(&m) h.db.Save(&m)
log.Trace().
Str("handler", "PollNetMapStream").
Str("machine", m.Name).
Str("channel", "Done").
Msg("Cancelling keepAlive channel")
cancelKeepAlive <- struct{}{} cancelKeepAlive <- struct{}{}
log.Trace().
Str("handler", "PollNetMapStream").
Str("machine", m.Name).
Str("channel", "Done").
Msg("Closing update channel")
h.closeUpdateChannel(&m) h.closeUpdateChannel(&m)
close(pollDataChan) close(pollDataChan)
log.Trace().
Str("handler", "PollNetMapStream").
Str("machine", m.Name).
Str("channel", "Done").
Msg("Closing pollData channel")
close(keepAliveChan) close(keepAliveChan)
log.Trace().
Str("handler", "PollNetMapStream").
Str("machine", m.Name).
Str("channel", "Done").
Msg("Closing keepAliveChan channel")
return false return false
} }