use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class BundleRouterInfos method main.
/**
* Usage: PersistentDataStore -i configDir -o toDir -c count
*
* Copy a random selection of 'count' router infos from configDir/netDb
* to 'toDir'. Skip your own router info, and old, hidden, unreachable, and
* introduced routers, and those from bad countries.
*
* @since 0.9.15
*/
public static void main(String[] args) {
Getopt g = new Getopt("PersistentDataStore", args, "i:o:c:");
String in = System.getProperty("user.home") + "/.i2p";
String out = "netDb";
int count = 200;
boolean error = false;
int c;
while ((c = g.getopt()) != -1) {
switch(c) {
case 'i':
in = g.getOptarg();
break;
case 'o':
out = g.getOptarg();
break;
case 'c':
String scount = g.getOptarg();
try {
count = Integer.parseInt(scount);
} catch (NumberFormatException nfe) {
error = true;
}
break;
case '?':
case ':':
default:
error = true;
}
}
if (error) {
usage();
System.exit(1);
}
Properties props = new Properties();
props.setProperty(GeoIP.PROP_GEOIP_DIR, System.getProperty("user.dir") + "/installer/resources");
GeoIP geoIP = new GeoIP(new I2PAppContext(props));
File confDir = new File(in);
File dbDir = new File(confDir, "netDb");
if (!dbDir.exists()) {
System.out.println("NetDB directory " + dbDir + " does not exist");
System.exit(1);
}
File myFile = new File(confDir, "router.info");
File toDir = new File(out);
toDir.mkdirs();
InputStream fis = null;
Hash me = null;
try {
fis = new BufferedInputStream(new FileInputStream(myFile));
RouterInfo ri = new RouterInfo();
// true = verify sig on read
ri.readBytes(fis, true);
me = ri.getIdentity().getHash();
} catch (IOException e) {
// System.out.println("Can't determine our identity");
} catch (DataFormatException e) {
// System.out.println("Can't determine our identity");
} finally {
if (fis != null)
try {
fis.close();
} catch (IOException ioe) {
}
}
int routerCount = 0;
List<File> toRead = new ArrayList<File>(2048);
for (int j = 0; j < Base64.ALPHABET_I2P.length(); j++) {
File subdir = new File(dbDir, PersistentDataStore.DIR_PREFIX + Base64.ALPHABET_I2P.charAt(j));
File[] files = subdir.listFiles(PersistentDataStore.RI_FILTER);
if (files == null)
continue;
routerCount += files.length;
for (int i = 0; i < files.length; i++) {
toRead.add(files[i]);
}
}
if (toRead.isEmpty()) {
System.out.println("No files to copy in " + dbDir);
System.exit(1);
}
Collections.shuffle(toRead);
int copied = 0;
long tooOld = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000L;
Map<String, String> ipMap = new HashMap<String, String>(count);
for (File file : toRead) {
if (copied >= count)
break;
Hash key = PersistentDataStore.getRouterInfoHash(file.getName());
if (key == null) {
System.out.println("Skipping bad " + file);
continue;
}
if (key.equals(me)) {
System.out.println("Skipping my RI");
continue;
}
fis = null;
try {
fis = new BufferedInputStream(new FileInputStream(file));
RouterInfo ri = new RouterInfo();
// true = verify sig on read
ri.readBytes(fis, true);
try {
fis.close();
} catch (IOException ioe) {
}
fis = null;
if (ri.getPublished() < tooOld) {
System.out.println("Skipping too old " + key);
continue;
}
if (ri.getCapabilities().contains("U")) {
System.out.println("Skipping unreachable " + key);
continue;
}
if (ri.getCapabilities().contains("K")) {
System.out.println("Skipping slow " + key);
continue;
}
Collection<RouterAddress> addrs = ri.getAddresses();
if (addrs.isEmpty()) {
System.out.println("Skipping hidden " + key);
continue;
}
boolean hasIntro = false;
boolean hasIPv4 = false;
boolean dupIP = false;
for (RouterAddress addr : addrs) {
if ("SSU".equals(addr.getTransportStyle()) && addr.getOption("ihost0") != null) {
hasIntro = true;
break;
}
String host = addr.getHost();
if (host != null && host.contains(".")) {
hasIPv4 = true;
geoIP.add(host);
String old = ipMap.put(host, file.getName());
if (old != null && !old.equals(file.getName())) {
dupIP = true;
break;
}
}
}
if (dupIP) {
System.out.println("Skipping dup IP " + key);
continue;
}
if (hasIntro) {
System.out.println("Skipping introduced " + key);
continue;
}
if (!hasIPv4) {
System.out.println("Skipping IPv6-only " + key);
continue;
}
File toFile = new File(toDir, file.getName());
// We could call ri.write() to avoid simultaneous change by the router
boolean ok = FileUtil.copy(file, toFile, true, true);
if (ok)
copied++;
else
System.out.println("Failed copy of " + file + " to " + toDir);
} catch (IOException e) {
System.out.println("Skipping bad " + file);
} catch (DataFormatException e) {
System.out.println("Skipping bad " + file);
} finally {
if (fis != null)
try {
fis.close();
} catch (IOException ioe) {
}
}
}
if (copied > 0) {
// now do all the geoip lookups, and delete any bad countries
geoIP.blockingLookup();
for (Map.Entry<String, String> e : ipMap.entrySet()) {
String co = geoIP.get(e.getKey());
if (co != null) {
if (BadCountries.contains(co)) {
String name = e.getValue();
File toFile = new File(toDir, name);
if (toFile.delete()) {
String full = geoIP.fullName(co);
if (full == null)
full = co;
System.out.println("Skipping " + full + ": " + name);
copied--;
}
}
}
}
}
if (copied > 0) {
System.out.println("Copied " + copied + " router info files to " + toDir);
} else {
System.out.println("Failed to copy any files to " + toDir);
System.exit(1);
}
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class MultiRouter method internalReseed.
private static void internalReseed() {
HashSet<RouterInfo> riSet = new HashSet<RouterInfo>();
for (Router r : _routers) {
riSet.addAll(r.getContext().netDb().getRouters());
}
for (Router r : _routers) {
for (RouterInfo ri : riSet) {
r.getContext().netDb().publish(ri);
}
}
_out.println(riSet.size() + " RouterInfos were reseeded");
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class NTCPTransport method outboundMessageReady.
protected void outboundMessageReady() {
OutNetMessage msg = getNextMessage();
if (msg != null) {
RouterInfo target = msg.getTarget();
RouterIdentity ident = target.getIdentity();
Hash ih = ident.calculateHash();
NTCPConnection con = null;
boolean isNew = false;
boolean fail = false;
synchronized (_conLock) {
con = _conByIdent.get(ih);
if (con == null) {
isNew = true;
RouterAddress addr = getTargetAddress(target);
if (addr != null) {
con = new NTCPConnection(_context, this, ident, addr);
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Send on a new con: " + con + " at " + addr + " for " + ih);
// Note that outbound conns go in the map BEFORE establishment
_conByIdent.put(ih, con);
} else {
// race, RI changed out from under us
// call afterSend below outside of conLock
fail = true;
}
}
}
if (fail) {
// race, RI changed out from under us, maybe SSU can handle it
if (_log.shouldLog(Log.WARN))
_log.warn("we bid on a peer who doesn't have an ntcp address? " + target);
afterSend(msg, false);
return;
}
if (isNew) {
// doesn't do anything yet, just enqueues it
con.send(msg);
// As of 0.9.12, don't send our info if the first message is
// doing the same (common when connecting to a floodfill).
// Also, put the info message after whatever we are trying to send
// (it's a priority queue anyway and the info is low priority)
// Prior to 0.9.12, Bob would not send his RI unless he had ours,
// but that's fixed in 0.9.12.
boolean shouldSkipInfo = false;
I2NPMessage m = msg.getMessage();
if (m.getType() == DatabaseStoreMessage.MESSAGE_TYPE) {
DatabaseStoreMessage dsm = (DatabaseStoreMessage) m;
if (dsm.getKey().equals(_context.routerHash())) {
shouldSkipInfo = true;
}
}
if (!shouldSkipInfo) {
con.enqueueInfoMessage();
} else if (_log.shouldLog(Log.INFO)) {
_log.info("SKIPPING INFO message: " + con);
}
try {
SocketChannel channel = SocketChannel.open();
con.setChannel(channel);
channel.configureBlocking(false);
_pumper.registerConnect(con);
con.getEstablishState().prepareOutbound();
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error opening a channel", ioe);
_context.statManager().addRateData("ntcp.outboundFailedIOEImmediate", 1);
con.close();
}
} else {
con.send(msg);
}
/*
NTCPConnection con = getCon(ident);
remove the race here
if (con != null) {
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Send on an existing con: " + con);
con.send(msg);
} else {
RouterAddress addr = msg.getTarget().getTargetAddress(STYLE);
if (addr != null) {
NTCPAddress naddr = new NTCPAddress(addr);
con = new NTCPConnection(_context, this, ident, naddr);
Hash ih = ident.calculateHash();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Send on a new con: " + con + " at " + addr + " for " + ih.toBase64());
NTCPConnection old = null;
synchronized (_conLock) {
old = (NTCPConnection)_conByIdent.put(ih, con);
}
if (old != null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Multiple connections on out ready, closing " + old + " and keeping " + con);
old.close();
}
con.enqueueInfoMessage(); // enqueues a netDb store of our own info
con.send(msg); // doesn't do anything yet, just enqueues it
try {
SocketChannel channel = SocketChannel.open();
con.setChannel(channel);
channel.configureBlocking(false);
_pumper.registerConnect(con);
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error opening a channel", ioe);
con.close();
}
} else {
con.close();
}
}
*/
}
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class TransportManager method getNextBid.
TransportBid getNextBid(OutNetMessage msg) {
int unreachableTransports = 0;
Hash peer = msg.getTarget().getIdentity().calculateHash();
Set<String> failedTransports = msg.getFailedTransports();
TransportBid rv = null;
for (Transport t : _transports.values()) {
if (t.isUnreachable(peer)) {
unreachableTransports++;
// this keeps GetBids() from banlisting for "no common transports"
// right after we banlisted for "unreachable on any transport" below...
msg.transportFailed(t.getStyle());
continue;
}
if (failedTransports.contains(t.getStyle())) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Skipping transport " + t.getStyle() + " as it already failed");
continue;
}
// we always want to try all transports, in case there is a faster bidirectional one
// already connected (e.g. peer only has a public PHTTP address, but they've connected
// to us via TCP, send via TCP)
TransportBid bid = t.bid(msg.getTarget(), msg.getMessageSize());
if (bid != null) {
if (bid.getLatencyMs() == TransportBid.TRANSIENT_FAIL)
// this keeps GetBids() from banlisting for "no common transports"
msg.transportFailed(t.getStyle());
else if ((rv == null) || (rv.getLatencyMs() > bid.getLatencyMs()))
rv = bid;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Transport " + t.getStyle() + " bid: " + bid + " currently winning? " + (rv == bid) + " (winning latency: " + rv.getLatencyMs() + " / " + rv + ")");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Transport " + t.getStyle() + " did not produce a bid");
if (t.isUnreachable(peer))
unreachableTransports++;
}
}
if (unreachableTransports >= _transports.size()) {
if (msg.getTarget().getIdentity().getSigningPublicKey().getType() == null) {
// we don't support his crypto
_context.statManager().addRateData("transport.banlistOnUnsupportedSigType", 1);
_context.banlist().banlistRouterForever(peer, _x("Unsupported signature type"));
} else if (unreachableTransports >= _transports.size() && countActivePeers() > 0) {
// Don't banlist if we aren't talking to anybody, as we may have a network connection issue
boolean incompat = false;
RouterInfo us = _context.router().getRouterInfo();
if (us != null) {
RouterIdentity id = us.getIdentity();
if (id.getSigType() != SigType.DSA_SHA1) {
String v = msg.getTarget().getVersion();
// NTCP is earlier than SSU, use that one
if (VersionComparator.comp(v, NTCPTransport.MIN_SIGTYPE_VERSION) < 0)
incompat = true;
}
}
if (incompat) {
// they don't support our crypto
_context.statManager().addRateData("transport.banlistOnUnsupportedSigType", 1);
_context.banlist().banlistRouter(peer, _x("No support for our signature type"), null, null, _context.clock().now() + SIGTYPE_BANLIST_DURATION);
} else {
_context.statManager().addRateData("transport.banlistOnUnreachable", msg.getLifetime(), msg.getLifetime());
_context.banlist().banlistRouter(peer, _x("Unreachable on any transport"));
}
}
} else if (rv == null) {
_context.statManager().addRateData("transport.noBidsYetNotAllUnreachable", unreachableTransports, msg.getLifetime());
}
return rv;
}
use of net.i2p.data.router.RouterInfo in project i2p.i2p by i2p.
the class SearchJob method continueSearch.
/**
* Send a series of searches to the next available peers as selected by
* the routing table, but making sure no more than SEARCH_BREDTH are outstanding
* at any time
*/
protected void continueSearch() {
if (_state.completed()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": Search already completed", new Exception("already completed"));
return;
}
int toCheck = getBredth() - _state.getPending().size();
if (toCheck <= 0) {
// too many already pending
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Too many searches already pending (pending: " + _state.getPending().size() + " max: " + getBredth() + ")");
requeuePending();
return;
}
int sent = 0;
Set<Hash> attempted = _state.getAttempted();
while (sent <= 0) {
// boolean onlyFloodfill = onlyQueryFloodfillPeers(getContext());
boolean onlyFloodfill = true;
if (_floodfillPeersExhausted && onlyFloodfill && _state.getPending().isEmpty()) {
if (_log.shouldLog(Log.WARN))
_log.warn(getJobId() + ": no non-floodfill peers left, and no more pending. Searched: " + _state.getAttempted().size() + " failed: " + _state.getFailed().size());
fail();
return;
}
List<Hash> closestHashes = getClosestRouters(_state.getTarget(), toCheck, attempted);
if ((closestHashes == null) || (closestHashes.isEmpty())) {
if (_state.getPending().isEmpty()) {
// we tried to find some peers, but there weren't any and no one else is going to answer
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": No peers left, and none pending! Already searched: " + _state.getAttempted().size() + " failed: " + _state.getFailed().size());
fail();
} else {
// no more to try, but we might get data or close peers from some outstanding requests
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": No peers left, but some are pending! Pending: " + _state.getPending().size() + " attempted: " + _state.getAttempted().size() + " failed: " + _state.getFailed().size());
requeuePending();
}
return;
} else {
attempted.addAll(closestHashes);
for (Hash peer : closestHashes) {
DatabaseEntry ds = _facade.getDataStore().get(peer);
if (ds == null) {
if (_log.shouldLog(Log.INFO))
_log.info("Next closest peer " + peer + " was only recently referred to us, sending a search for them");
getContext().netDb().lookupRouterInfo(peer, null, null, _timeoutMs);
} else if (!(ds.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO)) {
if (_log.shouldLog(Log.WARN))
_log.warn(getJobId() + ": Error selecting closest hash that wasnt a router! " + peer + " : " + ds.getClass().getName());
_state.replyTimeout(peer);
} else {
RouterInfo ri = (RouterInfo) ds;
if (!FloodfillNetworkDatabaseFacade.isFloodfill(ri)) {
_floodfillPeersExhausted = true;
if (onlyFloodfill)
continue;
}
if (ri.isHidden()) {
// || // allow querying banlisted, since its indirect
// getContext().banlist().isBanlisted(peer)) {
// dont bother
} else {
_state.addPending(peer);
sendSearch((RouterInfo) ds);
sent++;
}
}
}
/*
if (sent <= 0) {
// the (potentially) last peers being searched for could not be,
// er, searched for, so lets retry ASAP (causing either another
// peer to be selected, or the whole search to fail)
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": No new peer queued up, so we are going to requeue " +
"ourselves in our search for " + _state.getTarget().toBase64());
requeuePending(0);
}
*/
}
}
}
Aggregations