From 0d5a4dbe75b24e25cabb8c707570a659b4f33167 Mon Sep 17 00:00:00 2001 From: GustavoHMDS Date: Tue, 8 Sep 2026 01:25:52 -0300 Subject: [PATCH] =?UTF-8?q?adicionar=20um=20gerenciador=20de=20conex=C3=B5?= =?UTF-8?q?es=20que=20mantem=20um=20registro=20das=20conex=C3=B5es=20ativa?= =?UTF-8?q?s=20e=20cuida=20do=20seu=20encerramento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pitiupi/net/tcp/ConnectionManager.java | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 pitiupi/src/pitiupi/net/tcp/ConnectionManager.java diff --git a/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java b/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java new file mode 100644 index 0000000..823b43a --- /dev/null +++ b/pitiupi/src/pitiupi/net/tcp/ConnectionManager.java @@ -0,0 +1,160 @@ +package pitiupi.net.tcp; + +import pitiupi.control.PeerInfo; +import pitiupi.control.PeerListener; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class ConnectionManager implements PeerListener { + private final Logger logger; + private final Map publicConnections; + private final Map> privateConnections; + + public ConnectionManager() { + publicConnections = new ConcurrentHashMap<>(); + privateConnections = new ConcurrentHashMap<>(); + + logger = Logger.getLogger(getClass().getName()); + } + + public TcpConnection getPublicConnection(InetAddress address) { + return publicConnections.get(address); + } + + public void addPrivateConnection(InetAddress address, TcpConnection connection) { + List connections = + privateConnections.computeIfAbsent(connection.getAddress(), _ -> new ArrayList<>()); + + synchronized (connections) { + connections.add(connection); + } + } + public void addPublicConnection(InetAddress address, TcpConnection connection) { + TcpConnection oldConnection = publicConnections.put(connection.getAddress(), connection); + if (oldConnection != null && oldConnection != connection) { + closeConnection(oldConnection); + } + } + + public void closeConnection(TcpConnection connection, String reason) { + SysInfoMessage.sendSystemInfo(connection, SysInfoType.CONNECTION_CLOSED, reason); + closeConnection(connection); + } + public void closeConnection(TcpConnection connection) { + if (connection == null) return; + if (connection.isPrivate()) { + List connections = privateConnections.get(connection.getAddress()); + + if (connections != null) { + synchronized (connections) { + connections.remove(connection); + + if (connections.isEmpty()) privateConnections.remove(connection.getAddress(), connections); + } + } + } + else publicConnections.remove(connection.getAddress(), connection); + + try { + if (!connection.isClosed()) { + connection.close(); + } + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error closing TCP connection", ex); + } + } + + public void closeByAdress(InetAddress address, String reason) { + List connections = privateConnections.get(address); + for (TcpConnection connection : connections) { + SysInfoMessage.sendSystemInfo(connection, SysInfoType.CONNECTION_CLOSED, reason); + } + closeByAdress(address); + } + + public void closeByAdress(InetAddress address) { + TcpConnection publicConnection = publicConnections.remove(address); + + if (publicConnection != null) { + try { + publicConnection.close(); + } + catch (IOException ex) { + logger.log(Level.SEVERE, "Error closing TCP connection", ex); + } + + } + + List connections = privateConnections.remove(address); + + if (connections != null) { + synchronized (connections) { + for (TcpConnection connection : connections) { + try { + connection.close(); + } + catch (IOException ex) { + logger.log(Level.SEVERE, "Error closing TCP connection", ex); + } + } + connections.clear(); + } + } + } + + public void closeAllConnections(String reason) { + for (List connections : privateConnections.values()) { + for (TcpConnection connection : connections) { + SysInfoMessage.sendSystemInfo(connection, SysInfoType.CONNECTION_CLOSED, reason); + } + } + closeAllConnections(); + } + public void closeAllConnections() { + for (TcpConnection connection : publicConnections.values()) { + closeConnection(connection); + } + + synchronized (privateConnections) { + for (List connectionsList : privateConnections.values()) { + for (TcpConnection connection : connectionsList) { + closeConnection(connection); + } + privateConnections.clear(); + } + } + } + + /** + * Atualiza as conexões de acordo com os peers atualmente ativos. + * + *

Conexões associadas a peers que não estão mais ativos são encerradas + * e removidas.

+ * + * @param peers lista atualizada de peers ativos. + */ + @Override + public void onPeersChanged(List peers) { + Set activePeers = peers.stream().map(PeerInfo::getAddress).collect(Collectors.toSet()); + + for (InetAddress address : publicConnections.keySet()) { + if (!activePeers.contains(address)) { + closeByAdress(address); + } + } + for (InetAddress address : privateConnections.keySet()) { + if (!activePeers.contains(address)) { + closeByAdress(address); + } + } + } +}