diff --git a/src/main/java/org/qortal/network/task/ChannelAcceptTask.java b/src/main/java/org/qortal/network/task/ChannelAcceptTask.java index da04cf9a..57dbb04d 100644 --- a/src/main/java/org/qortal/network/task/ChannelAcceptTask.java +++ b/src/main/java/org/qortal/network/task/ChannelAcceptTask.java @@ -32,112 +32,105 @@ public class ChannelAcceptTask implements Task { @Override public void perform() throws InterruptedException { - Network network = Network.getInstance(); - SocketChannel socketChannel; + final Network network = Network.getInstance(); try { - if (network.getImmutableConnectedPeers().size() >= network.getMaxPeers()) { - // We have enough peers - LOGGER.debug("Ignoring pending incoming connections because the server is full"); + // Check if max peer limit is reached + int currentPeerCount = network.getImmutableConnectedPeers().size(); + if (currentPeerCount >= network.getMaxPeers()) { + LOGGER.debug("Incoming connection ignored: server is full ({} peers connected)", currentPeerCount); return; } - socketChannel = serverSocketChannel.accept(); - + // Accept new socket connection + SocketChannel socketChannel = serverSocketChannel.accept(); network.setInterestOps(serverSocketChannel, SelectionKey.OP_ACCEPT); + + // Handle null case for socketChannel + if (socketChannel == null) { + return; + } + + // Process the accepted connection + handleNewConnection(network, socketChannel); } catch (IOException e) { - return; - } - - // No connection actually accepted? - if (socketChannel == null) { - return; + LOGGER.error("Error during connection accept: {}", e.getMessage(), e); } + } + private void handleNewConnection(Network network, SocketChannel socketChannel) throws IOException { PeerAddress address = PeerAddress.fromSocket(socketChannel.socket()); List fixedNetwork = Settings.getInstance().getFixedNetwork(); + + // Check if peer is allowed in fixed network if (fixedNetwork != null && !fixedNetwork.isEmpty() && network.ipNotInFixedList(address, fixedNetwork)) { - try { - LOGGER.debug("Connection discarded from peer {} as not in the fixed network list", address); - socketChannel.close(); - } catch (IOException e) { - // IGNORE - } + LOGGER.debug("Connection rejected: peer {} not in fixed network list", address); + closeSocket(socketChannel); return; } - // We allow up to a maximum of maxPeers connected peers, of which... - // - maxDataPeers must be prearranged data connections (these are intentionally short-lived) - // - the remainder can be any regular peers - - // Firstly, determine the maximum limits + // Determine connection limits int maxPeers = Settings.getInstance().getMaxPeers(); int maxDataPeers = Settings.getInstance().getMaxDataPeers(); int maxRegularPeers = maxPeers - maxDataPeers; - // Next, obtain the current state - int connectedDataPeerCount = Network.getInstance().getImmutableConnectedDataPeers().size(); - int connectedRegularPeerCount = Network.getInstance().getImmutableConnectedNonDataPeers().size(); + int connectedDataPeers = network.getImmutableConnectedDataPeers().size(); + int connectedRegularPeers = network.getImmutableConnectedNonDataPeers().size(); - // Check if the incoming connection should be considered a data or regular peer boolean isDataPeer = ArbitraryDataFileManager.getInstance().isPeerRequestingData(address.getHost()); + boolean connectionLimitReached = (isDataPeer && connectedDataPeers >= maxDataPeers) + || (!isDataPeer && connectedRegularPeers >= maxRegularPeers); - // Finally, decide if we have any capacity for this incoming peer - boolean connectionLimitReached; - if (isDataPeer) { - connectionLimitReached = (connectedDataPeerCount >= maxDataPeers); - } - else { - connectionLimitReached = (connectedRegularPeerCount >= maxRegularPeers); - } - - // Extra maxPeers check just to be safe - if (Network.getInstance().getImmutableConnectedPeers().size() >= maxPeers) { + // Double-check maxPeers limit + if (network.getImmutableConnectedPeers().size() >= maxPeers) { connectionLimitReached = true; } if (connectionLimitReached) { - try { - // We have enough peers - LOGGER.debug("Connection discarded from peer {} because the server is full", address); - socketChannel.close(); - } catch (IOException e) { - // IGNORE - } + LOGGER.debug("Connection rejected: server is full for {} peer type", isDataPeer ? "data" : "regular"); + closeSocket(socketChannel); return; } + // Check NTP synchronization final Long now = NTP.getTime(); - Peer newPeer; + if (now == null) { + LOGGER.debug("Connection rejected: NTP time unavailable for peer {}", address); + closeSocket(socketChannel); + return; + } + // Accept the new peer + acceptPeer(network, socketChannel, address, isDataPeer); + } + + private void acceptPeer(Network network, SocketChannel socketChannel, PeerAddress address, boolean isDataPeer) { try { - if (now == null) { - LOGGER.debug("Connection discarded from peer {} due to lack of NTP sync", address); - socketChannel.close(); - return; - } - LOGGER.debug("Connection accepted from peer {}", address); - newPeer = new Peer(socketChannel); + Peer newPeer = new Peer(socketChannel); if (isDataPeer) { - newPeer.setMaxConnectionAge(Settings.getInstance().getMaxDataPeerConnectionTime() * 1000L); + long maxConnectionAge = Settings.getInstance().getMaxDataPeerConnectionTime() * 1000L; + newPeer.setMaxConnectionAge(maxConnectionAge); } newPeer.setIsDataPeer(isDataPeer); network.addConnectedPeer(newPeer); + // Notify the network that the peer is ready + network.onPeerReady(newPeer); } catch (IOException e) { - if (socketChannel.isOpen()) { - try { - LOGGER.debug("Connection failed from peer {} while connecting/closing", address); - socketChannel.close(); - } catch (IOException ce) { - // Couldn't close? - } - } - return; + LOGGER.error("Failed to accept peer {}: {}", address, e.getMessage(), e); + closeSocket(socketChannel); } + } - network.onPeerReady(newPeer); + private void closeSocket(SocketChannel socketChannel) { + if (socketChannel != null && socketChannel.isOpen()) { + try { + socketChannel.close(); + } catch (IOException e) { + LOGGER.error("Failed to close socket: {}", e.getMessage(), e); + } + } } }