Merge 00b1365bd13d45f437313b6b160218b50c519e0a into 8ffb0625a1edcf0b3d1ec2498b15a31ec38ade3c

This commit is contained in:
cwd.systems | 0KN 2024-11-27 17:12:02 +06:00 committed by GitHub
commit 2635596411
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

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