Commit aad730bc authored by Hiro's avatar Hiro 🏄
Browse files

This test the weird last_restarted first_seen fields mismatch bug in onionoo.

I have not been able to figure out why this bug appear and this evil hack might
fix it.

Update the tests and updater.
parent 0f4c48ee
Pipeline #36888 failed with stage
in 4 minutes and 19 seconds
......@@ -226,18 +226,6 @@ public class NodeStatus extends Document {
return this.lastSeenMillis;
}
private String lastRestarted;
public void setLastRestarted(Long lastRestarted) {
this.lastRestarted = null == lastRestarted ? null
: DateTimeHelper.format(lastRestarted);
}
public Long getLastRestarted() {
return this.lastRestarted == null ? null :
DateTimeHelper.parse(this.lastRestarted);
}
private int orPort;
public void setOrPort(int orPort) {
......
......@@ -195,11 +195,9 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
UptimeStatus uptimeStatus = this.documentStore.retrieve(
UptimeStatus.class, true, fingerprint);
if (uptimeStatus != null) {
if (detailsStatus.isRelay()) {
detailsStatus.setFirstSeenMillis(
uptimeStatus.getRelayHistory().first().getStartMillis()
);
}
detailsStatus.setFirstSeenMillis(
uptimeStatus.getRelayHistory().first().getStartMillis()
);
}
}
......@@ -375,17 +373,18 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
* We should check instead why the firstSeenMillis attribute get set to
* 0 but it might be digging to deep into the onionoo cave.
**/
logger.warn("last_restarted: {}", detailsStatus.getLastRestarted());
logger.warn("first_seen {}", detailsStatus.getFirstSeenMillis());
if (detailsStatus.getFirstSeenMillis()
> detailsStatus.getLastRestarted()) {
logger.warn("In the hack looop");
UptimeStatus uptimeStatus = this.documentStore.retrieve(
UptimeStatus.class, true, fingerprint);
if (uptimeStatus != null) {
if (!detailsStatus.isRelay()) {
detailsStatus.setFirstSeenMillis(
uptimeStatus.getBridgeHistory().first().getStartMillis()
);
}
detailsStatus.setFirstSeenMillis(
uptimeStatus.getBridgeHistory().first().getStartMillis()
);
}
}
......@@ -601,7 +600,6 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
updatedNodeStatus.setOrAddressesAndPorts(orAddressesAndPorts);
updatedNodeStatus.setLastSeenMillis(
nodeStatus.getLastSeenMillis());
updatedNodeStatus.setLastRestarted(nodeStatus.getLastRestarted());
updatedNodeStatus.setOrPort(orPort);
updatedNodeStatus.setDirPort(dirPort);
updatedNodeStatus.setRelayFlags(nodeStatus.getRelayFlags());
......@@ -665,8 +663,10 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
addressLastLookupTimes.put(nodeStatus.getAddress(),
nodeStatus.getLastRdnsLookup());
}
this.reverseDomainNameResolver.setAddresses(addressLastLookupTimes);
this.reverseDomainNameResolver.startReverseDomainNameLookups();
if (null != this.reverseDomainNameResolver) {
this.reverseDomainNameResolver.setAddresses(addressLastLookupTimes);
this.reverseDomainNameResolver.startReverseDomainNameLookups();
}
}
private SortedMap<String, LookupResult> geoIpLookupResults = new TreeMap<>();
......@@ -880,24 +880,27 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
new TreeMap<>();
private void finishReverseDomainNameLookups() {
this.reverseDomainNameResolver.finishReverseDomainNameLookups();
this.startedRdnsLookups =
this.reverseDomainNameResolver.getLookupStartMillis();
Map<String, SortedSet<String>> verifiedLookupResults =
this.reverseDomainNameResolver.getVerifiedLookupResults();
Map<String, SortedSet<String>> unverifiedLookupResults =
this.reverseDomainNameResolver.getUnverifiedLookupResults();
for (String fingerprint : this.currentRelays) {
NodeStatus nodeStatus = this.knownNodes.get(fingerprint);
SortedSet<String> verifiedHostNames =
verifiedLookupResults.get(nodeStatus.getAddress());
SortedSet<String> unverifiedHostNames =
unverifiedLookupResults.get(nodeStatus.getAddress());
if (null != verifiedHostNames) {
this.rdnsVerifiedLookupResults.put(fingerprint, verifiedHostNames);
}
if (null != unverifiedHostNames) {
this.rdnsUnverifiedLookupResults.put(fingerprint, unverifiedHostNames);
if (null != this.reverseDomainNameResolver) {
this.reverseDomainNameResolver.finishReverseDomainNameLookups();
this.startedRdnsLookups =
this.reverseDomainNameResolver.getLookupStartMillis();
Map<String, SortedSet<String>> verifiedLookupResults =
this.reverseDomainNameResolver.getVerifiedLookupResults();
Map<String, SortedSet<String>> unverifiedLookupResults =
this.reverseDomainNameResolver.getUnverifiedLookupResults();
for (String fingerprint : this.currentRelays) {
NodeStatus nodeStatus = this.knownNodes.get(fingerprint);
SortedSet<String> verifiedHostNames =
verifiedLookupResults.get(nodeStatus.getAddress());
SortedSet<String> unverifiedHostNames =
unverifiedLookupResults.get(nodeStatus.getAddress());
if (null != verifiedHostNames) {
this.rdnsVerifiedLookupResults.put(fingerprint, verifiedHostNames);
}
if (null != unverifiedHostNames) {
this.rdnsUnverifiedLookupResults.put(fingerprint, unverifiedHostNames);
}
}
}
}
......
......@@ -9,6 +9,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.torproject.descriptor.BridgePoolAssignment;
import org.torproject.descriptor.BridgeNetworkStatus;
import org.torproject.descriptor.Descriptor;
import org.torproject.descriptor.DescriptorParser;
import org.torproject.descriptor.DescriptorSourceFactory;
......@@ -16,6 +17,7 @@ import org.torproject.descriptor.ServerDescriptor;
import org.torproject.metrics.onionoo.docs.DetailsStatus;
import org.torproject.metrics.onionoo.docs.DocumentStoreFactory;
import org.torproject.metrics.onionoo.docs.DummyDocumentStore;
import org.torproject.metrics.onionoo.docs.UptimeStatus;
import org.junit.Before;
import org.junit.Test;
......@@ -80,7 +82,7 @@ public class NodeDetailsStatusUpdaterTest {
for (Descriptor desc : dp.parseDescriptors(descString.getBytes(),
new File("dummy"), "dummy")) {
assertTrue(desc.getClass().getName(), desc instanceof ServerDescriptor);
ndsu.processDescriptor(desc, true);
ndsu.processDescriptor(desc, false);
}
assertEquals(1, this.docStore.getPerformedStoreOperations());
assertEquals(1, this.docStore.storedDocuments.size());
......@@ -91,7 +93,7 @@ public class NodeDetailsStatusUpdaterTest {
new File("dummy"), "dummy")) {
assertTrue(desc.getClass().getName(),
desc instanceof BridgePoolAssignment);
ndsu.processDescriptor(desc, true);
ndsu.processDescriptor(desc, false);
}
assertEquals(1, this.docStore.getPerformedStoreOperations());
assertEquals(1, this.docStore.storedDocuments.size());
......@@ -99,14 +101,134 @@ public class NodeDetailsStatusUpdaterTest {
assertNotNull(dd);
}
@Test
public void testLastRestartedFirstSeen() {
UptimeStatus uptimeStatus = new UptimeStatus();
uptimeStatus.setFromDocumentString(UPTIME);
this.docStore.store(uptimeStatus, FPB);
NodeDetailsStatusUpdater ndsu = new NodeDetailsStatusUpdater(null, null);
DescriptorParser dp = DescriptorSourceFactory.createDescriptorParser();
/*
* When we read about a node for the first time we expect to set its status
* from the descriptor publised milliseconds minus the uptime millisecods.
*/
String descString = BRIDGE1;
for (Descriptor desc : dp.parseDescriptors(descString.getBytes(),
new File("dummy"), "dummy")) {
ndsu.processDescriptor(desc, false);
}
ndsu.updateStatuses();
assertEquals(2, this.docStore.getPerformedStoreOperations());
assertEquals(3, this.docStore.storedDocuments.size());
DetailsStatus dd = this.docStore.getDocument(DetailsStatus.class, FPB);
assertNotNull(dd);
assertEquals((long) dd.getDescPublished() - 113883000,
(long) dd.getLastRestarted());
dd.setFirstSeenMillis(dd.getLastRestarted());
this.docStore.store(dd, FPB);
/*
* The node is now restarted and a new network status document is read.
* We expect the last_restarted field to be equal to the descriptor
* published timestamp. The first_seen field is still equal to the previous
* uptime value.
*/
long lastRestarted = dd.getLastRestarted();
descString = BRIDGE1_RESTARTED + BRIDGES_STATUSES;
for (Descriptor desc : dp.parseDescriptors(descString.getBytes(),
new File("dummy"), "dummy")) {
ndsu.processDescriptor(desc, false);
}
ndsu.updateStatuses();
dd = this.docStore.getDocument(DetailsStatus.class, FPB);
assertNotNull(dd);
assertEquals((long) dd.getDescPublished(), (long) dd.getLastRestarted());
assertEquals((long) lastRestarted, (long) dd.getFirstSeenMillis());
descString = BRIDGE1_UPDATED;
for (Descriptor desc : dp.parseDescriptors(descString.getBytes(),
new File("dummy"), "dummy")) {
assertTrue(desc.getClass().getName(), desc instanceof ServerDescriptor);
ndsu.processDescriptor(desc, false);
}
dd = this.docStore.getDocument(DetailsStatus.class, FPB);
assertNotNull(dd);
assertEquals((long)
uptimeStatus.getBridgeHistory().first().getStartMillis(),
(long) dd.getFirstSeenMillis());
}
private static final String FP = "42CAF9C0588BBADDD338025E8F2D3CCF35CEEC25";
private static final String FPB = "6306C870BE7415EB7167ED2E9C1224F28B7E6C61";
private static final String FPB = "2D8C27AA9C2FEC3EC468D7ABE9C3EDCA3C86610A";
private static final String BPA = "@type bridge-pool-assignment 1.0\n"
+ "bridge-pool-assignment 2022-03-18 23:33:42\n"
+ "6306C870BE7415EB7167ED2E9C1224F28B7E6C61 moat "
+ "2D8C27AA9C2FEC3EC468D7ABE9C3EDCA3C86610A moat "
+ "transport=obfs4 ip=4 blocklist=ru\n";
private static final String UPTIME = "b 2022-03-17-21 864000";
private static final String BRIDGES_STATUSES = "@type bridge-network-status "
+ "1.2\n"
+ "published 2022-03-19 08:12:11\n"
+ "flag-thresholds stable-uptime=1990924 stable-mtbf=3896250 "
+ "fast-speed=57000 guard-wfu=98.000% guard-tk=691200 "
+ "guard-bw-inc-exits=3409000 guard-bw-exc-exits=3412000 "
+ "enough-mtbf=1 ignoring-advertised-bws=0\n"
+ "fingerprint BA44A889E64B93FAA2B114E02C2A279A8555C533\n"
+ "r cybergroot01 LYwnqpwv7D7EaNer6cPtyjyGYQo "
+ "x6XBQBBfnXIioM4LoD6bWpXqoFk 2022-03-17 08:42:16 10.245.66.84 55284 0\n"
+ "a [fd9f:2e19:3bcf::c2:91ab]:55284\n"
+ "s Running V2Dir Valid\n"
+ "w Bandwidth=2381\n"
+ "p reject 1-65535";
private static final String BRIDGE1_RESTARTED = "@type bridge-server-"
+ "descriptor 1.2\n"
+ "router DockerObfs4Bridge 10.136.176.127 50451 0 0\n"
+ "master-key-ed25519 J6M6MmuZ2joRKaihSB1LDym+WiuUeId8+9nvtI1Sd1M\n"
+ "platform Tor 0.4.6.10 on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1 HSDir=2 HSIntro=4-5 "
+ "HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2022-03-18 08:10:11\n"
+ "fingerprint 2D8C 27AA 9C2F EC3E C468 D7AB E9C3 EDCA 3C86 610A\n"
+ "uptime 0\n"
+ "bandwidth 1073741824 1073741824 81352\n"
+ "extra-info-digest 29ECA238A04F0D00E941B2CC430393604430B7D4 "
+ "X0jHhL7ygWblKzjoTGMG4Eikz8Sqo2X9eIbrKzVANNw\n"
+ "hidden-service-dir\n"
+ "contact somebody\n"
+ "bridge-distribution-request any\n"
+ "ntor-onion-key kysCjXGfMAx6AdejV2r34d59atkXFkvLNT/9ADcd73M\n"
+ "reject *:*\n"
+ "tunnelled-dir-server\n"
+ "router-digest-sha256 t+rUo6bm75/Qywapm5TTTnY2HGmxZqFAI1/ON2IxNP4\n"
+ "router-digest 78E7EDA527387064BB4410FC8BAED6DA0902BFE3\n";
private static final String BRIDGE1_UPDATED = "@type bridge-server-"
+ "descriptor 1.2\n"
+ "router DockerObfs4Bridge 10.136.176.127 50451 0 0\n"
+ "master-key-ed25519 J6M6MmuZ2joRKaihSB1LDym+WiuUeId8+9nvtI1Sd1M\n"
+ "platform Tor 0.4.6.10 on Linux\n"
+ "proto Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1 HSDir=2 HSIntro=4-5 "
+ "HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2022-03-20 08:07:11\n"
+ "fingerprint 2D8C 27AA 9C2F EC3E C468 D7AB E9C3 EDCA 3C86 610A\n"
+ "uptime 864000\n"
+ "bandwidth 1073741824 1073741824 81352\n"
+ "extra-info-digest 29ECA238A04F0D00E941B2CC430393604430B7D4 "
+ "X0jHhL7ygWblKzjoTGMG4Eikz8Sqo2X9eIbrKzVANNw\n"
+ "hidden-service-dir\n"
+ "contact somebody\n"
+ "bridge-distribution-request any\n"
+ "ntor-onion-key kysCjXGfMAx6AdejV2r34d59atkXFkvLNT/9ADcd73M\n"
+ "reject *:*\n"
+ "tunnelled-dir-server\n"
+ "router-digest-sha256 t+rUo6bm75/Qywapm5TTTnY2HGmxZqFAI1/ON2IxNP4\n"
+ "router-digest 78E7EDA527387064BB4410FC8BAED6DA0902BFE3\n";
private static final String BRIDGE1 = "@type bridge-server-descriptor 1.2\n"
+ "router DockerObfs4Bridge 10.136.176.127 50451 0 0\n"
+ "master-key-ed25519 J6M6MmuZ2joRKaihSB1LDym+WiuUeId8+9nvtI1Sd1M\n"
......@@ -114,7 +236,7 @@ public class NodeDetailsStatusUpdaterTest {
+ "proto Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1 HSDir=2 HSIntro=4-5 "
+ "HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 Relay=1-3\n"
+ "published 2022-03-17 08:07:11\n"
+ "fingerprint 6306 C870 BE74 15EB 7167 ED2E 9C12 24F2 8B7E 6C61\n"
+ "fingerprint 2D8C 27AA 9C2F EC3E C468 D7AB E9C3 EDCA 3C86 610A\n"
+ "uptime 113883\n"
+ "bandwidth 1073741824 1073741824 81352\n"
+ "extra-info-digest 29ECA238A04F0D00E941B2CC430393604430B7D4 "
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment