Merge pull request #134 from kradalby/loop-97
This commit is contained in:
commit
63fa475913
4 changed files with 44 additions and 22 deletions
21
app.go
21
app.go
|
@ -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")
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
31
poll.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue