Fix awg-ctrl hanging on the torrent flag; log out on an expired session

The torrent flag was read inside loops over users rows (users/stats,
peers, metrics) and each read queried the config table. SQLite has a
single connection here, so the nested query waited for it forever: the
first stats request or Prometheus scrape locked awg-ctrl for good, and
the panel showed no users and timed out.

- the block setting is kept in memory (loaded at start, updated on
  save), so the flag never touches the database
- the set of flagged IPs is taken once before the query, not per row
- regression test: collectMetrics must finish with users in the table

Panel: a 401 from the panel itself (its JWT not accepted) now returns to
the login screen; a 401 relayed from a node's awg-ctrl does not.
This commit is contained in:
2026-10-18 00:08:17 +03:00
parent a84845cecb
commit de8a32ac41
5 changed files with 85 additions and 11 deletions
+4 -2
View File
@@ -73,6 +73,7 @@ func (s *Server) routes() []route {
}),
R("GET", "/api/users/stats", true, a, func(c *rctx) (result, error) {
torrent := s.torrent.SeenSet()
rows, err := s.db.Query("SELECT name, ip, pub_key, key_gen FROM users WHERE vpn_key != ''")
if err != nil {
return result{}, err
@@ -88,7 +89,7 @@ func (s *Server) routes() []route {
ps := stats[pub]
list = append(list, ob{{"name", n}, {"ip", ip}, {"key_gen", kg}, {"online", ps.Online},
{"lastHandshake", ps.LastHandshake}, {"rx", ps.Rx}, {"tx", ps.Tx}, {"priority", s.shaping.PriorityOf(ip)},
{"torrent", s.torrent.Seen(ip)}})
{"torrent", torrent[ip]}})
}
rows.Close()
return ok(ob{{"users", list}})
@@ -138,6 +139,7 @@ func (s *Server) routes() []route {
}),
R("GET", "/api/peers", true, a, func(c *rctx) (result, error) {
torrent := s.torrent.SeenSet()
stats := s.getPeersData()
peers, err := s.peersAll()
if err != nil {
@@ -148,7 +150,7 @@ func (s *Server) routes() []route {
ps := stats[p.PubKey]
list = append(list, ob{{"pub_key", p.PubKey}, {"ip", p.IP}, {"psk_key", p.PskKey}, {"owner", p.Owner},
{"online", ps.Online}, {"lastHandshake", ps.LastHandshake}, {"rx", ps.Rx}, {"tx", ps.Tx},
{"priority", s.shaping.PriorityOf(p.IP)}, {"torrent", s.torrent.Seen(p.IP)}})
{"priority", s.shaping.PriorityOf(p.IP)}, {"torrent", torrent[p.IP]}})
}
return ok(ob{{"peers", list}})
}),