forked from Qortal/qortal
Added optional "senderPeerAddress" string to HELLO messages, to allow external IP changes to be detected without using a centralized service.
This commit is contained in:
parent
b1c1634950
commit
f007f9a86d
@ -48,6 +48,9 @@ public enum Handshake {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Make a note of the senderPeerAddress, as this should be our public IP
|
||||
Network.getInstance().ourPeerAddressUpdated(helloMessage.getSenderPeerAddress());
|
||||
|
||||
String versionString = helloMessage.getVersionString();
|
||||
|
||||
Matcher matcher = peer.VERSION_PATTERN.matcher(versionString);
|
||||
@ -87,8 +90,9 @@ public enum Handshake {
|
||||
public void action(Peer peer) {
|
||||
String versionString = Controller.getInstance().getVersionString();
|
||||
long timestamp = NTP.getTime();
|
||||
String senderPeerAddress = peer.getPeerData().getAddress().toString();
|
||||
|
||||
Message helloMessage = new HelloMessage(timestamp, versionString);
|
||||
Message helloMessage = new HelloMessage(timestamp, versionString, senderPeerAddress);
|
||||
if (!peer.sendMessage(helloMessage))
|
||||
peer.disconnect("failed to send HELLO");
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataFileManager;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataManager;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.block.BlockData;
|
||||
import org.qortal.data.network.PeerData;
|
||||
@ -117,6 +116,9 @@ public class Network {
|
||||
|
||||
private final Lock mergePeersLock = new ReentrantLock();
|
||||
|
||||
private List<String> ourExternalIpAddressHistory = new ArrayList<>();
|
||||
private String ourExternalIpAddress = null;
|
||||
|
||||
// Constructors
|
||||
|
||||
private Network() {
|
||||
@ -1102,6 +1104,65 @@ public class Network {
|
||||
return new GetUnconfirmedTransactionsMessage();
|
||||
}
|
||||
|
||||
|
||||
// External IP / peerAddress tracking
|
||||
|
||||
public void ourPeerAddressUpdated(String peerAddress) {
|
||||
if (peerAddress == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] parts = peerAddress.split(":");
|
||||
if (parts.length != 2) {
|
||||
return;
|
||||
}
|
||||
String host = parts[0];
|
||||
try {
|
||||
InetAddress addr = InetAddress.getByName(host);
|
||||
if (addr.isAnyLocalAddress() || addr.isSiteLocalAddress()) {
|
||||
// Ignore local addresses
|
||||
return;
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.ourExternalIpAddressHistory.add(host);
|
||||
|
||||
// Limit to 10 entries
|
||||
while (this.ourExternalIpAddressHistory.size() > 10) {
|
||||
this.ourExternalIpAddressHistory.remove(0);
|
||||
}
|
||||
|
||||
// If we've had 3 consecutive matching addresses, and they're different from
|
||||
// our stored IP address value, treat it as updated.
|
||||
|
||||
int size = this.ourExternalIpAddressHistory.size();
|
||||
if (size < 3) {
|
||||
// Need at least 3 readings
|
||||
return;
|
||||
}
|
||||
|
||||
String ip1 = this.ourExternalIpAddressHistory.get(size - 1);
|
||||
String ip2 = this.ourExternalIpAddressHistory.get(size - 2);
|
||||
String ip3 = this.ourExternalIpAddressHistory.get(size - 3);
|
||||
|
||||
if (!Objects.equals(ip1, this.ourExternalIpAddress)) {
|
||||
// Latest reading doesn't match our known value
|
||||
if (Objects.equals(ip1, ip2) && Objects.equals(ip1, ip3)) {
|
||||
// Last 3 readings were the same - i.e. more than one peer agreed on the new IP address
|
||||
this.ourExternalIpAddress = ip1;
|
||||
this.onExternalIpUpdate(ip1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onExternalIpUpdate(String ipAddress) {
|
||||
LOGGER.info("External IP address updated to {}", ipAddress);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Peer-management calls
|
||||
|
||||
public void noteToSelf(Peer peer) {
|
||||
|
@ -13,16 +13,18 @@ public class HelloMessage extends Message {
|
||||
|
||||
private final long timestamp;
|
||||
private final String versionString;
|
||||
private final String senderPeerAddress;
|
||||
|
||||
private HelloMessage(int id, long timestamp, String versionString) {
|
||||
private HelloMessage(int id, long timestamp, String versionString, String senderPeerAddress) {
|
||||
super(id, MessageType.HELLO);
|
||||
|
||||
this.timestamp = timestamp;
|
||||
this.versionString = versionString;
|
||||
this.senderPeerAddress = senderPeerAddress;
|
||||
}
|
||||
|
||||
public HelloMessage(long timestamp, String versionString) {
|
||||
this(-1, timestamp, versionString);
|
||||
public HelloMessage(long timestamp, String versionString, String senderPeerAddress) {
|
||||
this(-1, timestamp, versionString, senderPeerAddress);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
@ -33,12 +35,22 @@ public class HelloMessage extends Message {
|
||||
return this.versionString;
|
||||
}
|
||||
|
||||
public String getSenderPeerAddress() {
|
||||
return this.senderPeerAddress;
|
||||
}
|
||||
|
||||
public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws TransformationException {
|
||||
long timestamp = byteBuffer.getLong();
|
||||
|
||||
String versionString = Serialization.deserializeSizedString(byteBuffer, 255);
|
||||
|
||||
return new HelloMessage(id, timestamp, versionString);
|
||||
// Sender peer address added in v3.0, so is an optional field. Older versions won't send it.
|
||||
String senderPeerAddress = null;
|
||||
if (byteBuffer.hasRemaining()) {
|
||||
senderPeerAddress = Serialization.deserializeSizedString(byteBuffer, 255);
|
||||
}
|
||||
|
||||
return new HelloMessage(id, timestamp, versionString, senderPeerAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,6 +61,8 @@ public class HelloMessage extends Message {
|
||||
|
||||
Serialization.serializeSizedString(bytes, this.versionString);
|
||||
|
||||
Serialization.serializeSizedString(bytes, this.senderPeerAddress);
|
||||
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user