forked from I2P_Developers/i2p.i2p
Sybil: More refactoring to separate analysis and display
This commit is contained in:
24
apps/routerconsole/java/src/net/i2p/router/sybil/Pair.java
Normal file
24
apps/routerconsole/java/src/net/i2p/router/sybil/Pair.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package net.i2p.router.sybil;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import net.i2p.data.router.RouterInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pair of routers and the distance between them.
|
||||||
|
*
|
||||||
|
* @since 0.9.38 moved from SybilRenderer
|
||||||
|
*/
|
||||||
|
public class Pair implements Comparable<Pair> {
|
||||||
|
public final RouterInfo r1, r2;
|
||||||
|
public final BigInteger dist;
|
||||||
|
|
||||||
|
public Pair(RouterInfo ri1, RouterInfo ri2, BigInteger distance) {
|
||||||
|
r1 = ri1; r2 = ri2; dist = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(Pair p) {
|
||||||
|
return this.dist.compareTo(p.dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,7 @@ import net.i2p.router.TunnelPoolSettings;
|
|||||||
import net.i2p.router.crypto.FamilyKeyCrypto;
|
import net.i2p.router.crypto.FamilyKeyCrypto;
|
||||||
import net.i2p.router.peermanager.DBHistory;
|
import net.i2p.router.peermanager.DBHistory;
|
||||||
import net.i2p.router.peermanager.PeerProfile;
|
import net.i2p.router.peermanager.PeerProfile;
|
||||||
|
import net.i2p.router.sybil.Pair;
|
||||||
import net.i2p.router.sybil.Points;
|
import net.i2p.router.sybil.Points;
|
||||||
import net.i2p.router.tunnel.pool.TunnelPool;
|
import net.i2p.router.tunnel.pool.TunnelPool;
|
||||||
import net.i2p.router.util.HashDistance;
|
import net.i2p.router.util.HashDistance;
|
||||||
@ -247,27 +248,40 @@ public class SybilRenderer {
|
|||||||
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
|
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
|
||||||
|
|
||||||
// IP analysis
|
// IP analysis
|
||||||
renderIPGroupsFamily(out, buf, ris, points);
|
Map<String, List<RouterInfo>> fmap = calculateIPGroupsFamily(ris, points);
|
||||||
renderIPGroupsUs(out, buf, ris, points);
|
renderIPGroupsFamily(out, buf, fmap);
|
||||||
renderIPGroups32(out, buf, ris, points);
|
List<RouterInfo> ri32 = new ArrayList<RouterInfo>(4);
|
||||||
renderIPGroups24(out, buf, ris, points);
|
List<RouterInfo> ri24 = new ArrayList<RouterInfo>(4);
|
||||||
renderIPGroups16(out, buf, ris, points);
|
List<RouterInfo> ri16 = new ArrayList<RouterInfo>(4);
|
||||||
|
calculateIPGroupsUs(ris, points, ri32, ri24, ri16);
|
||||||
|
renderIPGroupsUs(out, buf, ri32, ri24, ri16);
|
||||||
|
Map<Integer, List<RouterInfo>> map = calculateIPGroups32(ris, points);
|
||||||
|
renderIPGroups32(out, buf, map);
|
||||||
|
map = calculateIPGroups24(ris, points);
|
||||||
|
renderIPGroups24(out, buf, map);
|
||||||
|
map = calculateIPGroups16(ris, points);
|
||||||
|
//renderIPGroups16(out, buf, map);
|
||||||
|
|
||||||
// Pairwise distance analysis
|
// Pairwise distance analysis
|
||||||
renderPairDistance(out, buf, ris, points);
|
List<Pair> pairs = new ArrayList<Pair>(PAIRMAX);
|
||||||
|
double avg = calculatePairDistance(ris, points, pairs);
|
||||||
|
renderPairDistance(out, buf, pairs, avg);
|
||||||
|
|
||||||
// Distance to our router analysis
|
// Distance to our router analysis
|
||||||
buf.append("<h3 id=\"ritoday\" class=\"sybils\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
|
buf.append("<h3 id=\"ritoday\" class=\"sybils\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, ourRKey, "our rkey", avgMinDist, ris, points);
|
calculateRouterInfo(ourRKey, "our rkey", ris, points);
|
||||||
|
renderRouterInfoHTML(out, buf, ourRKey, avgMinDist, ris);
|
||||||
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
||||||
Hash nkey = rkgen.getNextRoutingKey(us);
|
Hash nkey = rkgen.getNextRoutingKey(us);
|
||||||
buf.append("<h3 id=\"ritmrw\" class=\"sybils\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
|
buf.append("<h3 id=\"ritmrw\" class=\"sybils\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, nkey, "our rkey (tomorrow)", avgMinDist, ris, points);
|
calculateRouterInfo(nkey, "our rkey (tomorrow)", ris, points);
|
||||||
|
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris);
|
||||||
|
|
||||||
buf.append("<h3 id=\"dht\" class=\"sybils\">Closest Floodfills to Our Router Hash (DHT Neighbors if we are Floodfill)</h3>");
|
buf.append("<h3 id=\"dht\" class=\"sybils\">Closest Floodfills to Our Router Hash (DHT Neighbors if we are Floodfill)</h3>");
|
||||||
renderRouterInfoHTML(out, buf, us, "our router", avgMinDist, ris, points);
|
calculateRouterInfo(us, "our router", ris, points);
|
||||||
|
renderRouterInfoHTML(out, buf, us, avgMinDist, ris);
|
||||||
|
|
||||||
// Distance to our published destinations analysis
|
// Distance to our published destinations analysis
|
||||||
buf.append("<h3 id=\"dest\" class=\"sybils\">Floodfills Close to Our Destinations</h3>");
|
buf.append("<h3 id=\"dest\" class=\"sybils\">Floodfills Close to Our Destinations</h3>");
|
||||||
@ -288,11 +302,13 @@ public class SybilRenderer {
|
|||||||
String name = (in != null) ? DataHelper.escapeHTML(in.getSettings().getDestinationNickname()) : client.toBase64().substring(0,4);
|
String name = (in != null) ? DataHelper.escapeHTML(in.getSettings().getDestinationNickname()) : client.toBase64().substring(0,4);
|
||||||
buf.append("<h3 class=\"sybils\">Closest floodfills to the Routing Key for " + name + " (where we store our LS)</h3>");
|
buf.append("<h3 class=\"sybils\">Closest floodfills to the Routing Key for " + name + " (where we store our LS)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, rkey, name, avgMinDist, ris, points);
|
calculateRouterInfo(rkey, name, ris, points);
|
||||||
|
renderRouterInfoHTML(out, buf, rkey, avgMinDist, ris);
|
||||||
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
||||||
buf.append("<h3 class=\"sybils\">Closest floodfills to Tomorrow's Routing Key for " + name + " (where we will store our LS)</h3>");
|
buf.append("<h3 class=\"sybils\">Closest floodfills to Tomorrow's Routing Key for " + name + " (where we will store our LS)</h3>");
|
||||||
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
|
||||||
renderRouterInfoHTML(out, buf, nkey, name + " (tomorrow)", avgMinDist, ris, points);
|
calculateRouterInfo(nkey, name + " (tomorrow)", ris, points);
|
||||||
|
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profile analysis
|
// Profile analysis
|
||||||
@ -344,25 +360,29 @@ public class SybilRenderer {
|
|||||||
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
|
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
|
||||||
|
|
||||||
// IP analysis
|
// IP analysis
|
||||||
renderIPGroupsFamily(null, null, ris, points);
|
calculateIPGroupsFamily(ris, points);
|
||||||
renderIPGroupsUs(null, null, ris, points);
|
List<RouterInfo> ri32 = new ArrayList<RouterInfo>(4);
|
||||||
renderIPGroups32(null, null, ris, points);
|
List<RouterInfo> ri24 = new ArrayList<RouterInfo>(4);
|
||||||
renderIPGroups24(null, null, ris, points);
|
List<RouterInfo> ri16 = new ArrayList<RouterInfo>(4);
|
||||||
renderIPGroups16(null, null, ris, points);
|
calculateIPGroupsUs(ris, points, ri32, ri24, ri16);
|
||||||
|
calculateIPGroups32(ris, points);
|
||||||
|
calculateIPGroups24(ris, points);
|
||||||
|
calculateIPGroups16(ris, points);
|
||||||
|
|
||||||
// Pairwise distance analysis
|
// Pairwise distance analysis
|
||||||
renderPairDistance(null, null, ris, points);
|
List<Pair> pairs = new ArrayList<Pair>(PAIRMAX);
|
||||||
|
calculatePairDistance(ris, points, pairs);
|
||||||
|
|
||||||
// Distance to our router analysis
|
// Distance to our router analysis
|
||||||
// closest to our routing key today
|
// closest to our routing key today
|
||||||
Hash ourRKey = _context.router().getRouterInfo().getRoutingKey();
|
Hash ourRKey = _context.router().getRouterInfo().getRoutingKey();
|
||||||
renderRouterInfoHTML(null, null, ourRKey, "our rkey", avgMinDist, ris, points);
|
calculateRouterInfo(ourRKey, "our rkey", ris, points);
|
||||||
// closest to our routing key tomorrow
|
// closest to our routing key tomorrow
|
||||||
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
||||||
Hash nkey = rkgen.getNextRoutingKey(us);
|
Hash nkey = rkgen.getNextRoutingKey(us);
|
||||||
renderRouterInfoHTML(null, null, nkey, "our rkey (tomorrow)", avgMinDist, ris, points);
|
calculateRouterInfo(nkey, "our rkey (tomorrow)", ris, points);
|
||||||
// closest to us
|
// closest to us
|
||||||
renderRouterInfoHTML(null, null, us, "our router", avgMinDist, ris, points);
|
calculateRouterInfo(us, "our router", ris, points);
|
||||||
|
|
||||||
// Distance to our published destinations analysis
|
// Distance to our published destinations analysis
|
||||||
Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools();
|
Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools();
|
||||||
@ -380,10 +400,10 @@ public class SybilRenderer {
|
|||||||
TunnelPool in = clientInboundPools.get(client);
|
TunnelPool in = clientInboundPools.get(client);
|
||||||
String name = (in != null) ? DataHelper.escapeHTML(in.getSettings().getDestinationNickname()) : client.toBase64().substring(0,4);
|
String name = (in != null) ? DataHelper.escapeHTML(in.getSettings().getDestinationNickname()) : client.toBase64().substring(0,4);
|
||||||
// closest to routing key today
|
// closest to routing key today
|
||||||
renderRouterInfoHTML(null, null, rkey, name, avgMinDist, ris, points);
|
calculateRouterInfo(rkey, name, ris, points);
|
||||||
// closest to routing key tomorrow
|
// closest to routing key tomorrow
|
||||||
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
||||||
renderRouterInfoHTML(null, null, nkey, name + " (tomorrow)", avgMinDist, ris, points);
|
calculateRouterInfo(nkey, name + " (tomorrow)", ris, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profile analysis
|
// Profile analysis
|
||||||
@ -392,24 +412,14 @@ public class SybilRenderer {
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Pair implements Comparable<Pair> {
|
|
||||||
public final RouterInfo r1, r2;
|
|
||||||
public final BigInteger dist;
|
|
||||||
public Pair(RouterInfo ri1, RouterInfo ri2, BigInteger distance) {
|
|
||||||
r1 = ri1; r2 = ri2; dist = distance;
|
|
||||||
}
|
|
||||||
public int compareTo(Pair p) {
|
|
||||||
return this.dist.compareTo(p.dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @param pairs out parameter, sorted
|
||||||
* @param buf null for background analysis
|
* @param return average distance
|
||||||
|
* @since 0.9.38 split out from renderPairDistance()
|
||||||
*/
|
*/
|
||||||
private void renderPairDistance(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
private double calculatePairDistance(List<RouterInfo> ris, Map<Hash, Points> points,
|
||||||
|
List<Pair> pairs) {
|
||||||
int sz = ris.size();
|
int sz = ris.size();
|
||||||
List<Pair> pairs = new ArrayList<Pair>(PAIRMAX);
|
|
||||||
double total = 0;
|
double total = 0;
|
||||||
for (int i = 0; i < sz; i++) {
|
for (int i = 0; i < sz; i++) {
|
||||||
RouterInfo info1 = ris.get(i);
|
RouterInfo info1 = ris.get(i);
|
||||||
@ -430,22 +440,11 @@ public class SybilRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double avg = total / (sz * sz / 2d);
|
double avg = total / (sz * sz / 2d);
|
||||||
if (buf != null) {
|
|
||||||
buf.append("<h3 class=\"sybils\">Average Floodfill Distance is ").append(fmt.format(avg)).append("</h3>" +
|
|
||||||
"<h3 id=\"pairs\" class=\"sybils\">Closest Floodfill Pairs by Hash</h3>");
|
|
||||||
}
|
|
||||||
for (Pair p : pairs) {
|
for (Pair p : pairs) {
|
||||||
double distance = biLog2(p.dist);
|
double distance = biLog2(p.dist);
|
||||||
double point = MIN_CLOSE - distance;
|
double point = MIN_CLOSE - distance;
|
||||||
if (point < 0)
|
if (point < 0)
|
||||||
break; // sorted;
|
break; // sorted;
|
||||||
if (buf != null && point >= 2) {
|
|
||||||
// limit display
|
|
||||||
buf.append("<p class=\"hashdist\"><b>Hash Distance: ").append(fmt.format(distance)).append(": </b>" +
|
|
||||||
"</p>");
|
|
||||||
renderRouterInfo(buf, p.r1, null, false, false);
|
|
||||||
renderRouterInfo(buf, p.r2, null, false, false);
|
|
||||||
}
|
|
||||||
point *= PAIR_DISTANCE_FACTOR;
|
point *= PAIR_DISTANCE_FACTOR;
|
||||||
String b2 = p.r2.getHash().toBase64();
|
String b2 = p.r2.getHash().toBase64();
|
||||||
addPoints(points, p.r1.getHash(), point, "Very close (" + fmt.format(distance) +
|
addPoints(points, p.r1.getHash(), point, "Very close (" + fmt.format(distance) +
|
||||||
@ -454,12 +453,32 @@ public class SybilRenderer {
|
|||||||
addPoints(points, p.r2.getHash(), point, "Very close (" + fmt.format(distance) +
|
addPoints(points, p.r2.getHash(), point, "Very close (" + fmt.format(distance) +
|
||||||
") to other floodfill <a href=\"netdb?r=" + b1 + "\">" + b1 + "</a>");
|
") to other floodfill <a href=\"netdb?r=" + b1 + "\">" + b1 + "</a>");
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
return avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pairs sorted
|
||||||
|
*/
|
||||||
|
private void renderPairDistance(Writer out, StringBuilder buf, List<Pair> pairs, double avg) throws IOException {
|
||||||
|
buf.append("<h3 class=\"sybils\">Average Floodfill Distance is ").append(fmt.format(avg)).append("</h3>" +
|
||||||
|
"<h3 id=\"pairs\" class=\"sybils\">Closest Floodfill Pairs by Hash</h3>");
|
||||||
|
|
||||||
|
for (Pair p : pairs) {
|
||||||
|
double distance = biLog2(p.dist);
|
||||||
|
double point = MIN_CLOSE - distance;
|
||||||
|
// limit display
|
||||||
|
if (point < 2)
|
||||||
|
break; // sorted;
|
||||||
|
buf.append("<p class=\"hashdist\"><b>Hash Distance: ").append(fmt.format(distance)).append("</b>" +
|
||||||
|
"</p>");
|
||||||
|
renderRouterInfo(buf, p.r1, null, false, false);
|
||||||
|
renderRouterInfo(buf, p.r2, null, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private double closestDistance(Hash h, List<RouterInfo> ris) {
|
private double closestDistance(Hash h, List<RouterInfo> ris) {
|
||||||
BigInteger min = (new BigInteger("2")).pow(256);
|
BigInteger min = (new BigInteger("2")).pow(256);
|
||||||
@ -482,11 +501,11 @@ public class SybilRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class FooComparator implements Comparator<Integer>, Serializable {
|
private static class FooComparator implements Comparator<Integer>, Serializable {
|
||||||
private final ObjectCounter<Integer> _o;
|
private final Map<Integer, List<RouterInfo>> _o;
|
||||||
public FooComparator(ObjectCounter<Integer> o) { _o = o;}
|
public FooComparator(Map<Integer, List<RouterInfo>> o) { _o = o;}
|
||||||
public int compare(Integer l, Integer r) {
|
public int compare(Integer l, Integer r) {
|
||||||
// reverse by count
|
// reverse by count
|
||||||
int rv = _o.count(r) - _o.count(l);
|
int rv = _o.get(r).size() - _o.get(l).size();
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
return rv;
|
return rv;
|
||||||
// foward by IP
|
// foward by IP
|
||||||
@ -495,12 +514,12 @@ public class SybilRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class FoofComparator implements Comparator<String>, Serializable {
|
private static class FoofComparator implements Comparator<String>, Serializable {
|
||||||
private final ObjectCounter<String> _o;
|
private final Map<String, List<RouterInfo>> _o;
|
||||||
private final Collator _comp = Collator.getInstance();
|
private final Collator _comp = Collator.getInstance();
|
||||||
public FoofComparator(ObjectCounter<String> o) { _o = o;}
|
public FoofComparator(Map<String, List<RouterInfo>> o) { _o = o;}
|
||||||
public int compare(String l, String r) {
|
public int compare(String l, String r) {
|
||||||
// reverse by count
|
// reverse by count
|
||||||
int rv = _o.count(r) - _o.count(l);
|
int rv = _o.get(r).size() - _o.get(l).size();
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
return rv;
|
return rv;
|
||||||
// foward by name
|
// foward by name
|
||||||
@ -509,62 +528,74 @@ public class SybilRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @param ri32 out parameter
|
||||||
* @param buf null for background analysis
|
* @param ri24 out parameter
|
||||||
|
* @param ri16 out parameter
|
||||||
|
* @since 0.9.38 split out from renderIPGroupsUs()
|
||||||
*/
|
*/
|
||||||
private void renderIPGroupsUs(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
private void calculateIPGroupsUs(List<RouterInfo> ris, Map<Hash, Points> points,
|
||||||
|
List<RouterInfo> ri32, List<RouterInfo> ri24, List<RouterInfo> ri16) {
|
||||||
RouterInfo us = _context.router().getRouterInfo();
|
RouterInfo us = _context.router().getRouterInfo();
|
||||||
byte[] ourIP = getIP(us);
|
byte[] ourIP = getIP(us);
|
||||||
if (ourIP == null)
|
if (ourIP == null)
|
||||||
return;
|
return;
|
||||||
if (buf != null)
|
|
||||||
buf.append("<h3 id=\"ourIP\" class=\"sybils\">Floodfills close to Our IP</h3>");
|
|
||||||
boolean found = false;
|
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
byte[] ip = getIP(info);
|
||||||
if (ip == null)
|
if (ip == null)
|
||||||
continue;
|
continue;
|
||||||
if (ip[0] == ourIP[0] && ip[1] == ourIP[1]) {
|
if (ip[0] == ourIP[0] && ip[1] == ourIP[1]) {
|
||||||
if (buf != null)
|
|
||||||
buf.append("<p id=\"sybil_info\"><b>");
|
|
||||||
if (ip[2] == ourIP[2]) {
|
if (ip[2] == ourIP[2]) {
|
||||||
if (ip[3] == ourIP[3]) {
|
if (ip[3] == ourIP[3]) {
|
||||||
if (buf != null)
|
|
||||||
buf.append("Same IP as us");
|
|
||||||
addPoints(points, info.getHash(), POINTS_US32, "Same IP as us");
|
addPoints(points, info.getHash(), POINTS_US32, "Same IP as us");
|
||||||
} else {
|
} else {
|
||||||
if (buf != null)
|
|
||||||
buf.append("Same /24 as us");
|
|
||||||
addPoints(points, info.getHash(), POINTS_US24, "Same /24 as us");
|
addPoints(points, info.getHash(), POINTS_US24, "Same /24 as us");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (buf != null)
|
|
||||||
buf.append("Same /16 as us");
|
|
||||||
addPoints(points, info.getHash(), POINTS_US16, "Same /16 as us");
|
addPoints(points, info.getHash(), POINTS_US16, "Same /16 as us");
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void renderIPGroupsUs(Writer out, StringBuilder buf, List<RouterInfo> ri32,
|
||||||
|
List<RouterInfo> ri24, List<RouterInfo> ri16) throws IOException {
|
||||||
|
buf.append("<h3 id=\"ourIP\" class=\"sybils\">Floodfills close to Our IP</h3>");
|
||||||
|
boolean found = false;
|
||||||
|
for (RouterInfo info : ri32) {
|
||||||
|
buf.append("<p id=\"sybil_info\"><b>");
|
||||||
|
buf.append("Same IP as us");
|
||||||
buf.append(":</b></p>");
|
buf.append(":</b></p>");
|
||||||
renderRouterInfo(buf, info, null, false, false);
|
renderRouterInfo(buf, info, null, false, false);
|
||||||
}
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
for (RouterInfo info : ri24) {
|
||||||
|
buf.append("<p id=\"sybil_info\"><b>");
|
||||||
|
buf.append("Same /24 as us");
|
||||||
|
buf.append(":</b></p>");
|
||||||
|
renderRouterInfo(buf, info, null, false, false);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
for (RouterInfo info : ri16) {
|
||||||
|
buf.append("<p id=\"sybil_info\"><b>");
|
||||||
|
buf.append("Same /16 as us");
|
||||||
|
buf.append(":</b></p>");
|
||||||
|
renderRouterInfo(buf, info, null, false, false);
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
|
||||||
if (!found)
|
if (!found)
|
||||||
buf.append("<p class=\"notfound\">None</p>");
|
buf.append("<p class=\"notfound\">None</p>");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @since 0.9.38 split out from renderIPGroups32()
|
||||||
* @param buf null for background analysis
|
|
||||||
*/
|
*/
|
||||||
private void renderIPGroups32(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
private Map<Integer, List<RouterInfo>> calculateIPGroups32(List<RouterInfo> ris, Map<Hash, Points> points) {
|
||||||
if (buf != null)
|
|
||||||
buf.append("<h3 id=\"sameIP\" class=\"sybils\">Floodfills with the Same IP</h3>");
|
|
||||||
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
byte[] ip = getIP(info);
|
||||||
@ -573,27 +604,20 @@ public class SybilRenderer {
|
|||||||
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 4));
|
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 4));
|
||||||
oc.increment(x);
|
oc.increment(x);
|
||||||
}
|
}
|
||||||
List<Integer> foo = new ArrayList<Integer>();
|
Map<Integer, List<RouterInfo>> rv = new HashMap<Integer, List<RouterInfo>>();
|
||||||
for (Integer ii : oc.objects()) {
|
for (Integer ii : oc.objects()) {
|
||||||
int count = oc.count(ii);
|
int count = oc.count(ii);
|
||||||
if (count >= 2)
|
if (count >= 2)
|
||||||
foo.add(ii);
|
rv.put(ii, new ArrayList<RouterInfo>(4));
|
||||||
}
|
}
|
||||||
Collections.sort(foo, new FooComparator(oc));
|
for (Map.Entry<Integer, List<RouterInfo>> e : rv.entrySet()) {
|
||||||
boolean found = false;
|
Integer ii = e.getKey();
|
||||||
for (Integer ii : foo) {
|
|
||||||
int count = oc.count(ii);
|
int count = oc.count(ii);
|
||||||
int i = ii.intValue();
|
int i = ii.intValue();
|
||||||
int i0 = (i >> 24) & 0xff;
|
int i0 = (i >> 24) & 0xff;
|
||||||
int i1 = (i >> 16) & 0xff;
|
int i1 = (i >> 16) & 0xff;
|
||||||
int i2 = (i >> 8) & 0xff;
|
int i2 = (i >> 8) & 0xff;
|
||||||
int i3 = i & 0xff;
|
int i3 = i & 0xff;
|
||||||
String sip = i0 + "." + i1 + '.' + i2 + '.' + i3;
|
|
||||||
if (buf != null) {
|
|
||||||
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
|
|
||||||
.append(sip).append("&sybil\">").append(sip)
|
|
||||||
.append("</a>:</b></p>");
|
|
||||||
}
|
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
byte[] ip = getIP(info);
|
||||||
if (ip == null)
|
if (ip == null)
|
||||||
@ -606,29 +630,50 @@ public class SybilRenderer {
|
|||||||
continue;
|
continue;
|
||||||
if ((ip[3] & 0xff) != i3)
|
if ((ip[3] & 0xff) != i3)
|
||||||
continue;
|
continue;
|
||||||
found = true;
|
e.getValue().add(info);
|
||||||
if (buf != null)
|
|
||||||
renderRouterInfo(buf, info, null, false, false);
|
|
||||||
double point = POINTS32 * (count - 1);
|
double point = POINTS32 * (count - 1);
|
||||||
addPoints(points, info.getHash(), point, "Same IP with " + (count - 1) + " other" + (( count > 2) ? "s" : ""));
|
addPoints(points, info.getHash(), point, "Same IP with " + (count - 1) + " other" + (( count > 2) ? "s" : ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void renderIPGroups32(Writer out, StringBuilder buf, Map<Integer, List<RouterInfo>> map) throws IOException {
|
||||||
|
buf.append("<h3 id=\"sameIP\" class=\"sybils\">Floodfills with the Same IP</h3>");
|
||||||
|
List<Integer> foo = new ArrayList<Integer>(map.keySet());
|
||||||
|
Collections.sort(foo, new FooComparator(map));
|
||||||
|
boolean found = false;
|
||||||
|
for (Integer ii : foo) {
|
||||||
|
List<RouterInfo> ris = map.get(ii);
|
||||||
|
int count = ris.size();
|
||||||
|
int i = ii.intValue();
|
||||||
|
int i0 = (i >> 24) & 0xff;
|
||||||
|
int i1 = (i >> 16) & 0xff;
|
||||||
|
int i2 = (i >> 8) & 0xff;
|
||||||
|
int i3 = i & 0xff;
|
||||||
|
String sip = i0 + "." + i1 + '.' + i2 + '.' + i3;
|
||||||
|
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
|
||||||
|
.append(sip).append("&sybil\">").append(sip)
|
||||||
|
.append("</a>:</b></p>");
|
||||||
|
for (RouterInfo info : ris) {
|
||||||
|
found = true;
|
||||||
|
renderRouterInfo(buf, info, null, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
buf.append("<p class=\"notfound\">None</p>");
|
buf.append("<p class=\"notfound\">None</p>");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @since 0.9.38 split out from renderIPGroups24()
|
||||||
* @param buf null for background analysis
|
|
||||||
*/
|
*/
|
||||||
private void renderIPGroups24(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
private Map<Integer, List<RouterInfo>> calculateIPGroups24(List<RouterInfo> ris, Map<Hash, Points> points) {
|
||||||
if (buf != null)
|
|
||||||
buf.append("<h3 id=\"same24\" class=\"sybils\">Floodfills in the Same /24 (2 minimum)</h3>");
|
|
||||||
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
byte[] ip = getIP(info);
|
||||||
@ -637,26 +682,19 @@ public class SybilRenderer {
|
|||||||
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 3));
|
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 3));
|
||||||
oc.increment(x);
|
oc.increment(x);
|
||||||
}
|
}
|
||||||
List<Integer> foo = new ArrayList<Integer>();
|
Map<Integer, List<RouterInfo>> rv = new HashMap<Integer, List<RouterInfo>>();
|
||||||
for (Integer ii : oc.objects()) {
|
for (Integer ii : oc.objects()) {
|
||||||
int count = oc.count(ii);
|
int count = oc.count(ii);
|
||||||
if (count >= 2)
|
if (count >= 2)
|
||||||
foo.add(ii);
|
rv.put(ii, new ArrayList<RouterInfo>(4));
|
||||||
}
|
}
|
||||||
Collections.sort(foo, new FooComparator(oc));
|
for (Map.Entry<Integer, List<RouterInfo>> e : rv.entrySet()) {
|
||||||
boolean found = false;
|
Integer ii = e.getKey();
|
||||||
for (Integer ii : foo) {
|
|
||||||
int count = oc.count(ii);
|
int count = oc.count(ii);
|
||||||
int i = ii.intValue();
|
int i = ii.intValue();
|
||||||
int i0 = i >> 16;
|
int i0 = i >> 16;
|
||||||
int i1 = (i >> 8) & 0xff;
|
int i1 = (i >> 8) & 0xff;
|
||||||
int i2 = i & 0xff;
|
int i2 = i & 0xff;
|
||||||
String sip = i0 + "." + i1 + '.' + i2 + ".0/24";
|
|
||||||
if (buf != null) {
|
|
||||||
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
|
|
||||||
.append(sip).append("&sybil\">").append(sip)
|
|
||||||
.append("</a>:</b></p>");
|
|
||||||
}
|
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
byte[] ip = getIP(info);
|
||||||
if (ip == null)
|
if (ip == null)
|
||||||
@ -667,29 +705,49 @@ public class SybilRenderer {
|
|||||||
continue;
|
continue;
|
||||||
if ((ip[2] & 0xff) != i2)
|
if ((ip[2] & 0xff) != i2)
|
||||||
continue;
|
continue;
|
||||||
found = true;
|
e.getValue().add(info);
|
||||||
if (buf != null)
|
|
||||||
renderRouterInfo(buf, info, null, false, false);
|
|
||||||
double point = POINTS24 * (count - 1);
|
double point = POINTS24 * (count - 1);
|
||||||
addPoints(points, info.getHash(), point, "Same /24 IP with " + (count - 1) + " other" + (( count > 2) ? "s" : ""));
|
addPoints(points, info.getHash(), point, "Same /24 IP with " + (count - 1) + " other" + (( count > 2) ? "s" : ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void renderIPGroups24(Writer out, StringBuilder buf, Map<Integer, List<RouterInfo>> map) throws IOException {
|
||||||
|
buf.append("<h3 id=\"same24\" class=\"sybils\">Floodfills in the Same /24 (2 minimum)</h3>");
|
||||||
|
List<Integer> foo = new ArrayList<Integer>(map.keySet());
|
||||||
|
Collections.sort(foo, new FooComparator(map));
|
||||||
|
boolean found = false;
|
||||||
|
for (Integer ii : foo) {
|
||||||
|
List<RouterInfo> ris = map.get(ii);
|
||||||
|
int count = ris.size();
|
||||||
|
int i = ii.intValue();
|
||||||
|
int i0 = i >> 16;
|
||||||
|
int i1 = (i >> 8) & 0xff;
|
||||||
|
int i2 = i & 0xff;
|
||||||
|
String sip = i0 + "." + i1 + '.' + i2 + ".0/24";
|
||||||
|
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
|
||||||
|
.append(sip).append("&sybil\">").append(sip)
|
||||||
|
.append("</a>:</b></p>");
|
||||||
|
for (RouterInfo info : ris) {
|
||||||
|
found = true;
|
||||||
|
renderRouterInfo(buf, info, null, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
buf.append("<p class=\"notfound\">None</p>");
|
buf.append("<p class=\"notfound\">None</p>");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @since 0.9.38 split out from renderIPGroups16()
|
||||||
* @param buf null for background analysis
|
|
||||||
*/
|
*/
|
||||||
private void renderIPGroups16(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
private Map<Integer, List<RouterInfo>> calculateIPGroups16(List<RouterInfo> ris, Map<Hash, Points> points) {
|
||||||
if (buf != null)
|
|
||||||
buf.append("<h3 id=\"same16\" class=\"sybils\">Floodfills in the Same /16 (4 minimum)</h3>");
|
|
||||||
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
byte[] ip = getIP(info);
|
||||||
@ -698,16 +756,45 @@ public class SybilRenderer {
|
|||||||
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 2));
|
Integer x = Integer.valueOf((int) DataHelper.fromLong(ip, 0, 2));
|
||||||
oc.increment(x);
|
oc.increment(x);
|
||||||
}
|
}
|
||||||
List<Integer> foo = new ArrayList<Integer>();
|
Map<Integer, List<RouterInfo>> rv = new HashMap<Integer, List<RouterInfo>>();
|
||||||
for (Integer ii : oc.objects()) {
|
for (Integer ii : oc.objects()) {
|
||||||
int count = oc.count(ii);
|
int count = oc.count(ii);
|
||||||
if (count >= 4)
|
if (count >= 4)
|
||||||
foo.add(ii);
|
rv.put(ii, new ArrayList<RouterInfo>(8));
|
||||||
}
|
}
|
||||||
Collections.sort(foo, new FooComparator(oc));
|
for (Map.Entry<Integer, List<RouterInfo>> e : rv.entrySet()) {
|
||||||
|
Integer ii = e.getKey();
|
||||||
|
int count = oc.count(ii);
|
||||||
|
int i = ii.intValue();
|
||||||
|
int i0 = i >> 8;
|
||||||
|
int i1 = i & 0xff;
|
||||||
|
for (RouterInfo info : ris) {
|
||||||
|
byte[] ip = getIP(info);
|
||||||
|
if (ip == null)
|
||||||
|
continue;
|
||||||
|
if ((ip[0] & 0xff) != i0)
|
||||||
|
continue;
|
||||||
|
if ((ip[1] & 0xff) != i1)
|
||||||
|
continue;
|
||||||
|
e.getValue().add(info);
|
||||||
|
double point = POINTS16 * (count - 1);
|
||||||
|
addPoints(points, info.getHash(), point, "Same /16 IP with " + (count - 1) + " other" + (( count > 2) ? "s" : ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void renderIPGroups16(Writer out, StringBuilder buf, Map<Integer, List<RouterInfo>> map) throws IOException {
|
||||||
|
buf.append("<h3 id=\"same16\" class=\"sybils\">Floodfills in the Same /16 (4 minimum)</h3>");
|
||||||
|
List<Integer> foo = new ArrayList<Integer>(map.keySet());
|
||||||
|
Collections.sort(foo, new FooComparator(map));
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Integer ii : foo) {
|
for (Integer ii : foo) {
|
||||||
int count = oc.count(ii);
|
List<RouterInfo> ris = map.get(ii);
|
||||||
|
int count = ris.size();
|
||||||
int i = ii.intValue();
|
int i = ii.intValue();
|
||||||
int i0 = i >> 8;
|
int i0 = i >> 8;
|
||||||
int i1 = i & 0xff;
|
int i1 = i & 0xff;
|
||||||
@ -718,36 +805,21 @@ public class SybilRenderer {
|
|||||||
.append("</a></b></p>");
|
.append("</a></b></p>");
|
||||||
}
|
}
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
byte[] ip = getIP(info);
|
|
||||||
if (ip == null)
|
|
||||||
continue;
|
|
||||||
if ((ip[0] & 0xff) != i0)
|
|
||||||
continue;
|
|
||||||
if ((ip[1] & 0xff) != i1)
|
|
||||||
continue;
|
|
||||||
found = true;
|
found = true;
|
||||||
// limit display
|
renderRouterInfo(buf, info, null, false, false);
|
||||||
//renderRouterInfo(buf, info, null, false, false);
|
|
||||||
double point = POINTS16 * (count - 1);
|
|
||||||
addPoints(points, info.getHash(), point, "Same /16 IP with " + (count - 1) + " other" + (( count > 2) ? "s" : ""));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
|
||||||
if (!found)
|
if (!found)
|
||||||
buf.append("<p class=\"notfound\">None</p>");
|
buf.append("<p class=\"notfound\">None</p>");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @since 0.9.38 split out from renderIPGroupsFamily()
|
||||||
* @param buf null for background analysis
|
|
||||||
*/
|
*/
|
||||||
private void renderIPGroupsFamily(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
private Map<String, List<RouterInfo>> calculateIPGroupsFamily(List<RouterInfo> ris, Map<Hash, Points> points) {
|
||||||
if (buf != null)
|
|
||||||
buf.append("<h3 id=\"samefamily\" class=\"sybils\">Floodfills in the same Family</h3><div class=\"sybil_container\">");
|
|
||||||
ObjectCounter<String> oc = new ObjectCounter<String>();
|
ObjectCounter<String> oc = new ObjectCounter<String>();
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
String fam = info.getOption("family");
|
String fam = info.getOption("family");
|
||||||
@ -756,26 +828,21 @@ public class SybilRenderer {
|
|||||||
oc.increment(fam);
|
oc.increment(fam);
|
||||||
}
|
}
|
||||||
List<String> foo = new ArrayList<String>(oc.objects());
|
List<String> foo = new ArrayList<String>(oc.objects());
|
||||||
Collections.sort(foo, new FoofComparator(oc));
|
Map<String, List<RouterInfo>> rv = new HashMap<String, List<RouterInfo>>(foo.size());
|
||||||
FamilyKeyCrypto fkc = _context.router().getFamilyKeyCrypto();
|
FamilyKeyCrypto fkc = _context.router().getFamilyKeyCrypto();
|
||||||
String ourFamily = fkc != null ? fkc.getOurFamilyName() : null;
|
String ourFamily = fkc != null ? fkc.getOurFamilyName() : null;
|
||||||
boolean found = false;
|
|
||||||
for (String s : foo) {
|
for (String s : foo) {
|
||||||
int count = oc.count(s);
|
int count = oc.count(s);
|
||||||
|
List<RouterInfo> list = new ArrayList<RouterInfo>(count);
|
||||||
|
rv.put(s, list);
|
||||||
String ss = DataHelper.escapeHTML(s);
|
String ss = DataHelper.escapeHTML(s);
|
||||||
if (buf != null && count > 1) {
|
|
||||||
buf.append("<p class=\"family\"><b>").append(count).append(" floodfills in family: <a href=\"/netdb?fam=")
|
|
||||||
.append(ss).append("&sybil\">").append(ss).append("</a></b></p>");
|
|
||||||
}
|
|
||||||
for (RouterInfo info : ris) {
|
for (RouterInfo info : ris) {
|
||||||
String fam = info.getOption("family");
|
String fam = info.getOption("family");
|
||||||
if (fam == null)
|
if (fam == null)
|
||||||
continue;
|
continue;
|
||||||
if (!fam.equals(s))
|
if (!fam.equals(s))
|
||||||
continue;
|
continue;
|
||||||
found = true;
|
list.add(info);
|
||||||
// limit display
|
|
||||||
//renderRouterInfo(buf, info, null, false, false);
|
|
||||||
double point = POINTS_FAMILY;
|
double point = POINTS_FAMILY;
|
||||||
if (fkc != null && s.equals(ourFamily)) {
|
if (fkc != null && s.equals(ourFamily)) {
|
||||||
if (fkc.verifyOurFamily(info))
|
if (fkc.verifyOurFamily(info))
|
||||||
@ -789,7 +856,33 @@ public class SybilRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (buf != null) {
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void renderIPGroupsFamily(Writer out, StringBuilder buf, Map<String, List<RouterInfo>> map) throws IOException {
|
||||||
|
buf.append("<h3 id=\"samefamily\" class=\"sybils\">Floodfills in the same Family</h3><div class=\"sybil_container\">");
|
||||||
|
List<String> foo = new ArrayList<String>(map.keySet());
|
||||||
|
Collections.sort(foo, new FoofComparator(map));
|
||||||
|
FamilyKeyCrypto fkc = _context.router().getFamilyKeyCrypto();
|
||||||
|
String ourFamily = fkc != null ? fkc.getOurFamilyName() : null;
|
||||||
|
boolean found = false;
|
||||||
|
for (String s : foo) {
|
||||||
|
List<RouterInfo> list = map.get(s);
|
||||||
|
int count = list.size();
|
||||||
|
String ss = DataHelper.escapeHTML(s);
|
||||||
|
if (count > 1) {
|
||||||
|
buf.append("<p class=\"family\"><b>").append(count).append(" floodfills in family: <a href=\"/netdb?fam=")
|
||||||
|
.append(ss).append("&sybil\">").append(ss).append("</a></b></p>");
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
//for (RouterInfo info : ris) {
|
||||||
|
// limit display
|
||||||
|
//renderRouterInfo(buf, info, null, false, false);
|
||||||
|
//}
|
||||||
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
buf.append("<p class=\"notfound\">None</p>");
|
buf.append("<p class=\"notfound\">None</p>");
|
||||||
buf.append("</div>");
|
buf.append("</div>");
|
||||||
@ -797,7 +890,6 @@ public class SybilRenderer {
|
|||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static final long DAY = 24*60*60*1000L;
|
private static final long DAY = 24*60*60*1000L;
|
||||||
|
|
||||||
@ -878,13 +970,33 @@ public class SybilRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param out null for background analysis
|
* @param usName HTML escaped
|
||||||
* @param buf null for background analysis
|
* @param ris will be re-sorted in place
|
||||||
|
* @since 0.9.38 split out from renderRouterInfoHTML()
|
||||||
|
*/
|
||||||
|
private void calculateRouterInfo(Hash us, String usName,
|
||||||
|
List<RouterInfo> ris, Map<Hash, Points> points) {
|
||||||
|
Collections.sort(ris, new RouterInfoRoutingKeyComparator(us));
|
||||||
|
int count = Math.min(MAX, ris.size());
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
RouterInfo ri = ris.get(i);
|
||||||
|
BigInteger bidist = HashDistance.getDistance(us, ri.getHash());
|
||||||
|
double dist = biLog2(bidist);
|
||||||
|
double point = MIN_CLOSE - dist;
|
||||||
|
if (point <= 0)
|
||||||
|
break;
|
||||||
|
point *= OUR_KEY_FACTOR;
|
||||||
|
addPoints(points, ri.getHash(), point, "Very close (" + fmt.format(dist) + ") to our key " + usName + ": " + us.toBase64());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render routers closer than MIN_CLOSE up to MAX routers
|
||||||
|
* @param ris sorted, closest first
|
||||||
* @param usName HTML escaped
|
* @param usName HTML escaped
|
||||||
*/
|
*/
|
||||||
private void renderRouterInfoHTML(Writer out, StringBuilder buf, Hash us, String usName, double avgMinDist,
|
private void renderRouterInfoHTML(Writer out, StringBuilder buf, Hash us, double avgMinDist,
|
||||||
List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
List<RouterInfo> ris) throws IOException {
|
||||||
Collections.sort(ris, new RouterInfoRoutingKeyComparator(us));
|
|
||||||
double min = 256;
|
double min = 256;
|
||||||
double max = 0;
|
double max = 0;
|
||||||
double tot = 0;
|
double tot = 0;
|
||||||
@ -894,14 +1006,10 @@ public class SybilRenderer {
|
|||||||
int medIdx = isEven ? (count / 2) - 1 : (count / 2);
|
int medIdx = isEven ? (count / 2) - 1 : (count / 2);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
RouterInfo ri = ris.get(i);
|
RouterInfo ri = ris.get(i);
|
||||||
double dist;
|
double dist = renderRouterInfo(buf, ri, us, false, false);
|
||||||
if (buf != null) {
|
if (dist < MIN_CLOSE)
|
||||||
dist = renderRouterInfo(buf, ri, us, false, false);
|
break;
|
||||||
} else {
|
if (dist < avgMinDist) {
|
||||||
BigInteger bidist = HashDistance.getDistance(us, ri.getHash());
|
|
||||||
dist = biLog2(bidist);
|
|
||||||
}
|
|
||||||
if (buf != null && dist < avgMinDist) {
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
//buf.append("<p><b>Not to worry, but above router is closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
|
//buf.append("<p><b>Not to worry, but above router is closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
@ -922,23 +1030,18 @@ public class SybilRenderer {
|
|||||||
median = dist;
|
median = dist;
|
||||||
else if (i == medIdx + 1 && isEven)
|
else if (i == medIdx + 1 && isEven)
|
||||||
median = (median + dist) / 2;
|
median = (median + dist) / 2;
|
||||||
double point = MIN_CLOSE - dist;
|
|
||||||
if (point > 0) {
|
|
||||||
point *= OUR_KEY_FACTOR;
|
|
||||||
addPoints(points, ri.getHash(), point, "Very close (" + fmt.format(dist) + ") to our key " + usName + ": " + us.toBase64());
|
|
||||||
}
|
}
|
||||||
if (i >= MAX - 1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (buf != null) {
|
|
||||||
double avg = tot / count;
|
double avg = tot / count;
|
||||||
buf.append("<p id=\"sybil_totals\"><b>Totals for " + count + " floodfills: </b><span class=\"netdb_name\">MIN:</span > " + fmt.format(min) + " <span class=\"netdb_name\">AVG:</span> " +
|
buf.append("<p id=\"sybil_totals\"><b>Totals for " + count +
|
||||||
fmt.format(avg) + " <span class=\"netdb_name\">MEDIAN:</span> " + fmt.format(median) + " <span class=\"netdb_name\">MAX:</span> " + fmt.format(max) + "</p>\n");
|
" floodfills: </b><span class=\"netdb_name\">MIN:</span > " + fmt.format(min) +
|
||||||
|
" <span class=\"netdb_name\">AVG:</span> " + fmt.format(avg) +
|
||||||
|
" <span class=\"netdb_name\">MEDIAN:</span> " + fmt.format(median) +
|
||||||
|
" <span class=\"netdb_name\">MAX:</span> " + fmt.format(max) +
|
||||||
|
"</p>\n");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For debugging
|
* For debugging
|
||||||
|
Reference in New Issue
Block a user