From 713ab652f8dd27259241e8105f1379246b82273d Mon Sep 17 00:00:00 2001 From: lax1dude <cgiacun@gmail.com> Date: Sat, 18 Jan 2025 13:19:17 -0800 Subject: [PATCH] {1.4} Reduce lock contention in shared world relay --- .../SharedWorldRelay-Latest.jar | Bin 258185 -> 258677 bytes .../v1_8/sp/relay/server/Constants.java | 2 +- .../v1_8/sp/relay/server/EaglerSPRelay.java | 178 +++++++++--------- .../v1_8/sp/relay/server/EaglerSPServer.java | 15 +- 4 files changed, 107 insertions(+), 88 deletions(-) diff --git a/sp-relay/SharedWorldRelay/SharedWorldRelay-Latest.jar b/sp-relay/SharedWorldRelay/SharedWorldRelay-Latest.jar index 2c4ed8f20ad3c53f9cf4e57d0be7f7533bbdf167..3ced95dcaaccd481a985a5067dcfd420ae14eafd 100644 GIT binary patch delta 17877 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 BuU-HE delta 17337 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 diff --git a/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/Constants.java b/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/Constants.java index 0e002f4a..d94c53d0 100644 --- a/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/Constants.java +++ b/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/Constants.java @@ -17,7 +17,7 @@ package net.lax1dude.eaglercraft.v1_8.sp.relay.server; */ public class Constants { - public static final String versionName = "1.3"; + public static final String versionName = "1.4"; public static final String versionBrand = "lax1dude"; public static final int protocolVersion = 1; diff --git a/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPRelay.java b/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPRelay.java index 2ff4ee95..c4141b27 100644 --- a/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPRelay.java +++ b/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPRelay.java @@ -13,7 +13,10 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.java_websocket.WebSocket; import org.java_websocket.handshake.ClientHandshake; @@ -23,7 +26,7 @@ import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.*; import net.lax1dude.eaglercraft.v1_8.sp.relay.server.RateLimiter.RateLimit; /** - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. + * Copyright (c) 2022-2025 lax1dude. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -87,27 +90,19 @@ public class EaglerSPRelay extends WebSocketServer { long millis = Util.millis(); pendingToClose.clear(); clientToClose.clear(); - synchronized(pendingConnections) { - Iterator<Entry<WebSocket,PendingConnection>> itr = pendingConnections.entrySet().iterator(); - while(itr.hasNext()) { - Entry<WebSocket,PendingConnection> etr = itr.next(); - if(millis - etr.getValue().openTime > 1000l) { - pendingToClose.add(etr.getKey()); - itr.remove(); - } + pendingConnections.entrySet().forEach((etr) -> { + if(millis - etr.getValue().openTime > 1000l) { + pendingToClose.add(etr.getKey()); } - } - synchronized(clientConnections) { - Iterator<EaglerSPClient> itr = clientConnections.values().iterator(); - while(itr.hasNext()) { - EaglerSPClient cl = itr.next(); - if(millis - cl.createdOn > 15000l) { - clientToClose.add(cl); - } + }); + clientConnections.values().forEach((cl) -> { + if(millis - cl.createdOn > 15000l) { + clientToClose.add(cl); } - } + }); if(!pendingToClose.isEmpty()) { for(WebSocket cl : pendingToClose) { + pendingConnections.remove(cl); cl.close(); } pendingToClose.clear(); @@ -173,12 +168,17 @@ public class EaglerSPRelay extends WebSocketServer { } - private static final Map<WebSocket,PendingConnection> pendingConnections = new HashMap<>(); private static final Map<String,EaglerSPClient> clientIds = new HashMap<>(); - private static final Map<WebSocket,EaglerSPClient> clientConnections = new HashMap<>(); private static final Map<String,EaglerSPServer> serverCodes = new HashMap<>(); - private static final Map<WebSocket,EaglerSPServer> serverConnections = new HashMap<>(); + + private static final ConcurrentMap<WebSocket,PendingConnection> pendingConnections = new ConcurrentHashMap<>(); + private static final ConcurrentMap<WebSocket,EaglerSPClient> clientConnections = new ConcurrentHashMap<>(); + private static final ConcurrentMap<WebSocket,EaglerSPServer> serverConnections = new ConcurrentHashMap<>(); + + private static final ReadWriteLock clientAddressSetsLock = new ReentrantReadWriteLock(); private static final Map<String,List<EaglerSPClient>> clientAddressSets = new HashMap<>(); + + private static final ReadWriteLock serverAddressSetsLock = new ReentrantReadWriteLock(); private static final Map<String,List<EaglerSPServer>> serverAddressSets = new HashMap<>(); @Override @@ -202,23 +202,23 @@ public class EaglerSPRelay extends WebSocketServer { addr = arg0.getRemoteSocketAddress().getAddress().getHostAddress().toLowerCase(); } - int totalCons = 0; - synchronized(pendingConnections) { - Iterator<PendingConnection> pendingItr = pendingConnections.values().iterator(); - while(pendingItr.hasNext()) { - if(pendingItr.next().address.equals(addr)) { - ++totalCons; - } + int[] totalCons = new int[1]; + pendingConnections.values().forEach((con) -> { + if(con.address.equals(addr)) { + ++totalCons[0]; } - } - synchronized(clientAddressSets) { + }); + clientAddressSetsLock.readLock().lock(); + try { List<EaglerSPClient> lst = clientAddressSets.get(addr); if(lst != null) { - totalCons += lst.size(); + totalCons[0] += lst.size(); } + }finally { + clientAddressSetsLock.readLock().unlock(); } - if(totalCons >= config.getConnectionsPerIP()) { + if(totalCons[0] >= config.getConnectionsPerIP()) { logger.debug("[{}]: Too many connections are open on this address", (Object) arg0.getAttachment()); arg0.send(RelayPacketFEDisconnectClient.ratelimitPacketTooMany); arg0.close(); @@ -229,18 +229,13 @@ public class EaglerSPRelay extends WebSocketServer { PendingConnection waiting = new PendingConnection(millis, addr); logger.debug("[{}]: Connection opened", arg0.getRemoteSocketAddress()); - synchronized(pendingConnections) { - pendingConnections.put(arg0, waiting); - } + pendingConnections.put(arg0, waiting); } @Override public void onMessage(WebSocket arg0, ByteBuffer arg1) { DataInputStream sid = new DataInputStream(new ByteBufferInputStream(arg1)); - PendingConnection waiting; - synchronized(pendingConnections) { - waiting = pendingConnections.remove(arg0); - } + PendingConnection waiting = pendingConnections.remove(arg0); try { RelayPacket pkt = RelayPacket.readPacket(sid, EaglerSPRelay.logger); if(waiting != null) { @@ -265,13 +260,16 @@ public class EaglerSPRelay extends WebSocketServer { return; } boolean fuck = false; - synchronized(serverAddressSets) { + serverAddressSetsLock.readLock().lock(); + try { List<EaglerSPServer> lst = serverAddressSets.get(waiting.address); if(lst != null) { if(lst.size() >= config.getWorldsPerIP()) { fuck = true; } } + }finally { + serverAddressSetsLock.readLock().unlock(); } if(fuck) { logger.debug("[{}]: Too many worlds are open on this address", (Object) arg0.getAttachment()); @@ -310,16 +308,18 @@ public class EaglerSPRelay extends WebSocketServer { arg0.send(RelayPacket.writePacket(ipkt, EaglerSPRelay.logger)); logger.debug("[{}][Relay -> Server] PKT 0x00: Assign join code: {}", (Object) arg0.getAttachment(), code); - synchronized(serverConnections) { - serverConnections.put(arg0, srv); - } - synchronized(serverAddressSets) { + serverConnections.put(arg0, srv); + + serverAddressSetsLock.writeLock().lock(); + try { List<EaglerSPServer> lst = serverAddressSets.get(srv.serverAddress); if(lst == null) { lst = new ArrayList<>(); serverAddressSets.put(srv.serverAddress, lst); } lst.add(srv); + }finally { + serverAddressSetsLock.writeLock().unlock(); } srv.send(new RelayPacket01ICEServers(EaglerSPRelayConfigRelayList.relayServers)); logger.debug("[{}][Relay -> Server] PKT 0x01: Send ICE server list to server", (Object) arg0.getAttachment()); @@ -362,16 +362,17 @@ public class EaglerSPRelay extends WebSocketServer { ipkt.connectionCode = id; arg0.send(RelayPacket.writePacket(ipkt, EaglerSPRelay.logger)); srv.handleNewClient(cl); - synchronized(clientConnections) { - clientConnections.put(arg0, cl); - } - synchronized(clientAddressSets) { + clientConnections.put(arg0, cl); + clientAddressSetsLock.writeLock().lock(); + try { List<EaglerSPClient> lst = clientAddressSets.get(cl.address); if(lst == null) { lst = new ArrayList<>(); clientAddressSets.put(cl.address, lst); } lst.add(cl); + }finally { + clientAddressSetsLock.writeLock().unlock(); } cl.send(new RelayPacket01ICEServers(EaglerSPRelayConfigRelayList.relayServers)); logger.debug("[{}][Relay -> Client] PKT 0x01: Send ICE server list to client", (Object) arg0.getAttachment()); @@ -403,10 +404,7 @@ public class EaglerSPRelay extends WebSocketServer { arg0.close(); } }else { - EaglerSPServer srv; - synchronized(serverConnections) { - srv = serverConnections.get(arg0); - } + EaglerSPServer srv = serverConnections.get(arg0); if(srv != null) { if(!srv.handle(pkt)) { logger.debug("[{}]: Server sent invalid packet: {}", (Object) arg0.getAttachment(), pkt.getClass().getSimpleName()); @@ -415,10 +413,7 @@ public class EaglerSPRelay extends WebSocketServer { arg0.close(); } }else { - EaglerSPClient cl; - synchronized(clientConnections) { - cl = clientConnections.get(arg0); - } + EaglerSPClient cl = clientConnections.get(arg0); if(cl != null) { if(!cl.handle(pkt)) { logger.debug("[{}]: Client sent invalid packet: {}", (Object) arg0.getAttachment(), pkt.getClass().getSimpleName()); @@ -448,16 +443,14 @@ public class EaglerSPRelay extends WebSocketServer { @Override public void onClose(WebSocket arg0, int arg1, String arg2, boolean arg3) { - EaglerSPServer srv; - synchronized(serverConnections) { - srv = serverConnections.remove(arg0); - } + EaglerSPServer srv = serverConnections.remove(arg0); if(srv != null) { logger.debug("[{}]: Server closed, code: {}", (Object) arg0.getAttachment(), srv.code); synchronized(serverCodes) { serverCodes.remove(srv.code); } - synchronized(serverAddressSets) { + serverAddressSetsLock.writeLock().lock(); + try { List<EaglerSPServer> lst = serverAddressSets.get(srv.serverAddress); if(lst != null) { lst.remove(srv); @@ -465,26 +458,26 @@ public class EaglerSPRelay extends WebSocketServer { serverAddressSets.remove(srv.serverAddress); } } + }finally { + serverAddressSetsLock.writeLock().unlock(); } - ArrayList<EaglerSPClient> clientList; - synchronized(clientConnections) { - clientList = new ArrayList<>(clientConnections.values()); - } + final ArrayList<EaglerSPClient> clientList = new ArrayList<>(); + clientConnections.values().forEach((cl) -> { + if(cl.server == srv) { + clientList.add(cl); + } + }); Iterator<EaglerSPClient> itr = clientList.iterator(); while(itr.hasNext()) { EaglerSPClient cl = itr.next(); - if(cl.server == srv) { - logger.debug("[{}]: Disconnecting client: {} (id: {})", (Object) cl.socket.getAttachment(), cl.id); - cl.socket.close(); - } + logger.debug("[{}]: Disconnecting client: {} (id: {})", (Object) cl.socket.getAttachment(), cl.id); + cl.socket.close(); } }else { - EaglerSPClient cl; - synchronized(clientConnections) { - cl = clientConnections.remove(arg0); - } + EaglerSPClient cl = clientConnections.remove(arg0); if(cl != null) { - synchronized(clientAddressSets) { + clientAddressSetsLock.writeLock().lock(); + try { List<EaglerSPClient> lst = clientAddressSets.get(cl.address); if(lst != null) { lst.remove(cl); @@ -492,6 +485,8 @@ public class EaglerSPRelay extends WebSocketServer { clientAddressSets.remove(cl.address); } } + }finally { + clientAddressSetsLock.writeLock().unlock(); } logger.debug("[{}]: Client closed, id: {}", (Object) arg0.getAttachment(), cl.id); synchronized(clientIds) { @@ -511,21 +506,36 @@ public class EaglerSPRelay extends WebSocketServer { if(arg0 != null) arg0.close(); } + @Override + public void stop() throws InterruptedException { + // Handle internal WebSocketServer crashes + Thread killServer = new Thread(() -> { + try { + Thread.sleep(5000l); + }catch(InterruptedException ex) { + } + logger.error("WebSocketServer stopped, but the process is still running, calling System.exit to hopefully restart!"); + System.exit(-1); + }, "Terminator"); + killServer.setDaemon(true); + killServer.start(); + super.stop(); + } + private List<RelayPacket07LocalWorlds.LocalWorld> getLocalWorlds(String addr) { List<RelayPacket07LocalWorlds.LocalWorld> lst = new ArrayList<>(); - synchronized(serverAddressSets) { + serverAddressSetsLock.readLock().lock(); + try { List<EaglerSPServer> srvs = serverAddressSets.get(addr); - if(srvs != null) { - if(srvs.size() == 0) { - serverAddressSets.remove(addr); - }else { - for(EaglerSPServer s : srvs) { - if(!s.serverHidden) { - lst.add(new RelayPacket07LocalWorlds.LocalWorld(s.serverName, s.code)); - } + if(srvs != null && srvs.size() > 0) { + for(EaglerSPServer s : srvs) { + if(!s.serverHidden) { + lst.add(new RelayPacket07LocalWorlds.LocalWorld(s.serverName, s.code)); } } } + }finally { + serverAddressSetsLock.readLock().unlock(); } return lst; } diff --git a/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPServer.java b/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPServer.java index 75e4fb14..16c1fd62 100644 --- a/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPServer.java +++ b/sp-relay/SharedWorldRelay/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/server/EaglerSPServer.java @@ -73,7 +73,10 @@ public class EaglerSPServer { public boolean handle(RelayPacket _packet) throws IOException { if(_packet instanceof RelayPacket03ICECandidate) { RelayPacket03ICECandidate packet = (RelayPacket03ICECandidate)_packet; - EaglerSPClient cl = clients.get(packet.peerId); + EaglerSPClient cl; + synchronized(clients) { + cl = clients.get(packet.peerId); + } if(cl != null) { if(LoginState.assertEquals(cl, LoginState.SENT_ICE_CANDIDATE)) { cl.state = LoginState.RECIEVED_ICE_CANIDATE; @@ -87,7 +90,10 @@ public class EaglerSPServer { return true; }else if(_packet instanceof RelayPacket04Description) { RelayPacket04Description packet = (RelayPacket04Description)_packet; - EaglerSPClient cl = clients.get(packet.peerId); + EaglerSPClient cl; + synchronized(clients) { + cl = clients.get(packet.peerId); + } if(cl != null) { if(LoginState.assertEquals(cl, LoginState.SENT_DESCRIPTION)) { cl.state = LoginState.RECIEVED_DESCRIPTION; @@ -101,7 +107,10 @@ public class EaglerSPServer { return true; }else if(_packet instanceof RelayPacketFEDisconnectClient) { RelayPacketFEDisconnectClient packet = (RelayPacketFEDisconnectClient)_packet; - EaglerSPClient cl = clients.get(packet.clientId); + EaglerSPClient cl; + synchronized(clients) { + cl = clients.get(packet.clientId); + } if(cl != null) { cl.handleServerDisconnectClient(packet); EaglerSPRelay.logger.debug("[{}][Server -> Relay -> Client] PKT 0xFE: Disconnect: {}: {}", (Object) cl.socket.getAttachment(),