fix: resolve nethernet connection, ban deadlock, and nil RemoteAddr crashes

This commit is contained in:
2026-07-12 15:30:55 +07:00
parent abe84fb542
commit 0e2c2f072a
4 changed files with 113 additions and 32 deletions
+47 -8
View File
@@ -349,33 +349,64 @@ func (srv *Server) listen(l Listener) {
wg.Add(1)
go func() {
defer wg.Done()
defer func() {
if r := recover(); r != nil {
srv.conf.Log.Error(fmt.Sprintf("panic handling connection: %v", r))
_ = c.Close()
}
}()
name := c.IdentityData().DisplayName
xuid := c.IdentityData().XUID
uuidStr := c.IdentityData().Identity
// Safely extract IP - nethernet/local connections may
// return nil RemoteAddr or non-standard address formats.
ip := ""
if addr := c.RemoteAddr(); addr != nil {
if host, _, err := net.SplitHostPort(addr.String()); err == nil {
ip = host
} else {
ip = addr.String()
addrStr := addr.String()
if addrStr != "" {
if host, _, err := net.SplitHostPort(addrStr); err == nil {
ip = host
} else {
ip = addrStr
}
}
}
srv.conf.Log.Debug("Player connecting...", "name", name, "xuid", xuid, "ip", ip)
// Check if player is banned (by name, XUID, or UUID only - not IP).
if entry, banned := player.Bans.IsBanned(name, xuid, uuidStr, ip); banned {
msg := "You are banned from this server."
if entry.Reason != "" {
msg += " Reason: " + entry.Reason
}
if !entry.ExpiresAt.IsZero() {
timeLeft := time.Until(entry.ExpiresAt).Round(time.Second)
msg = fmt.Sprintf("You are banned from this server. Remaining time: %v", timeLeft)
if timeLeft > 0 {
msg += fmt.Sprintf(" Remaining: %v", timeLeft)
}
}
srv.conf.Log.Debug("Player banned, rejecting.", "name", name)
_ = c.WritePacket(&packet.Disconnect{Message: msg})
_ = c.Close()
return
}
if srv.PlayerCount() >= 14 && !strings.EqualFold(name, "XTarnaWijaya") && !strings.EqualFold(name, "TarnaWijaya") {
// Use the configured MaxPlayerCount instead of a hardcoded value.
// Admins bypass the player limit.
if srv.PlayerCount() >= srv.MaxPlayerCount() &&
!strings.EqualFold(name, "XTarnaWijaya") &&
!strings.EqualFold(name, "TarnaWijaya") {
srv.conf.Log.Debug("Server full, rejecting.", "name", name)
_ = c.WritePacket(&packet.Disconnect{Message: "Server is full."})
_ = c.Close()
return
}
if msg, ok := srv.conf.Allower.Allow(c.RemoteAddr(), c.IdentityData(), c.ClientData()); !ok {
srv.conf.Log.Debug("Player not allowed.", "name", name, "msg", msg)
_ = c.WritePacket(&packet.Disconnect{HideDisconnectionScreen: msg == "", Message: msg})
_ = c.Close()
return
@@ -469,12 +500,20 @@ func (srv *Server) finaliseConn(ctx context.Context, conn session.Conn, l Listen
if err := conn.StartGameContext(ctx, data); err != nil {
_ = l.Disconnect(conn, "Connection timeout.")
srv.conf.Log.Debug("spawn failed: "+err.Error(), "raddr", conn.RemoteAddr())
raddr := "nethernet"
if addr := conn.RemoteAddr(); addr != nil {
raddr = addr.String()
}
srv.conf.Log.Debug("spawn failed: "+err.Error(), "raddr", raddr)
return
}
if _, ok := srv.Player(id); ok {
_ = l.Disconnect(conn, "Already logged in.")
srv.conf.Log.Debug("spawn failed: already logged in", "raddr", conn.RemoteAddr())
raddr := "nethernet"
if addr := conn.RemoteAddr(); addr != nil {
raddr = addr.String()
}
srv.conf.Log.Debug("spawn failed: already logged in", "raddr", raddr)
return
}
_ = conn.WritePacket(&packet.ItemRegistry{Items: srv.customItems})