mirror of
https://github.com/Qortal/qortal.git
synced 2025-04-01 17:55:54 +00:00
Merge 00b1365bd13d45f437313b6b160218b50c519e0a into 8ffb0625a1edcf0b3d1ec2498b15a31ec38ade3c
This commit is contained in:
commit
2635596411
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user