fix: force-close user connections on removal, fix UDP upload/download counters, use self-hosted releases
CI / Test (push) Has been cancelled
CI / Build (amd64, linux) (push) Has been cancelled
CI / Build (arm64, linux) (push) Has been cancelled
CI / Build & Push Docker Image (push) Has been cancelled
CI / Release (push) Has been cancelled

- service.go: call CloseUserConnections() before RemoveUsers() so banned/reset
  users are disconnected immediately instead of waiting for natural timeout
  (upstream issue #32, PR pending 4+ months)

- conntracker.go: swap UnwrapPacketReader/Writer upload/download counters for
  UDP PacketConn path — Reader=upload, Writer=download to match TCP path
  (upstream issue #55)

- xbctl/main.go: change downloadBase to JP01 Gitea so xbctl upgrade pulls
  self-hosted patched releases instead of upstream
This commit is contained in:
2026-06-18 15:14:09 +09:00
parent 0a29338e1f
commit fce60b8ad3
3 changed files with 17 additions and 7 deletions
+3 -5
View File
@@ -30,7 +30,7 @@ const (
serviceName = "xboard-node.service" serviceName = "xboard-node.service"
serviceFilePath = "/etc/systemd/system/xboard-node.service" serviceFilePath = "/etc/systemd/system/xboard-node.service"
defaultInstallRoot = "/etc/xboard-node" defaultInstallRoot = "/etc/xboard-node"
downloadBase = "https://github.com/cedar2025/xboard-node/releases" downloadBase = "http://103.112.1.141:3000/will/xboard-node"
) )
var ( var (
@@ -593,10 +593,8 @@ func ensureRoot(cmd string) error {
} }
func resolveDownloadURL(artifact, version string) string { func resolveDownloadURL(artifact, version string) string {
if version == "latest" { // Gitea release download URL: {base}/releases/download/{tag}/{file}
return downloadBase + "/latest/download/" + artifact return downloadBase + "/releases/download/" + version + "/" + artifact
}
return downloadBase + "/download/" + version + "/" + artifact
} }
func downloadFile(url, dest string) error { func downloadFile(url, dest string) error {
+2 -2
View File
@@ -791,14 +791,14 @@ func (c *trackedPacketConn) UnwrapPacketReader() (N.PacketReader, []N.CountFunc)
if c.us == nil { if c.us == nil {
return c.PacketConn, nil return c.PacketConn, nil
} }
return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.download)} return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.upload)}
} }
func (c *trackedPacketConn) UnwrapPacketWriter() (N.PacketWriter, []N.CountFunc) { func (c *trackedPacketConn) UnwrapPacketWriter() (N.PacketWriter, []N.CountFunc) {
if c.us == nil { if c.us == nil {
return c.PacketConn, nil return c.PacketConn, nil
} }
return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.upload)} return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.download)}
} }
func (c *trackedPacketConn) Upstream() any { return c.PacketConn } func (c *trackedPacketConn) Upstream() any { return c.PacketConn }
+12
View File
@@ -838,6 +838,18 @@ func (s *Service) applyUserDelta(ctx context.Context, action string, deltaUsers
return return
} }
// Force-close active connections for removed users before revoking
// credentials. Without this, existing long-lived connections
// (QUIC/TCP) persist until natural timeout — subscription resets
// and bans would not take immediate effect.
if s.kernel.Capabilities().ForceCloseUser {
for _, u := range deltaUsers {
if err := s.kernel.CloseUserConnections(ctx, u.UUID); err != nil {
nlog.Core().Debug(fmt.Sprintf("CloseUserConnections(%s): %v", u.UUID, err))
}
}
}
prevUsers, prevHash := s.prepareUserState(filtered) prevUsers, prevHash := s.prepareUserState(filtered)
removed, err := s.kernel.RemoveUsers(deltaUsers) removed, err := s.kernel.RemoveUsers(deltaUsers)
if err != nil { if err != nil {