more IPv6 bugfixes

pull/1/head
Michael Peter Christen 11 years ago
parent b31db00010
commit e1bc768f9d

@ -68,7 +68,7 @@ public class MessageSend_p {
// open an editor page for the message
// first ask if the other peer is online, and also what kind of document it accepts
final Map<String, String> result = Protocol.permissionMessage(sb.peers, hash);
final Map<String, String> result = Protocol.permissionMessage(sb.peers.targetAddress(hash), hash);
//System.out.println("DEBUG: permission request result = " + result.toString());
String peerName;
Seed targetPeer = null;
@ -106,7 +106,7 @@ public class MessageSend_p {
prop.putXML("mode_permission_message", message);
prop.putHTML("mode_permission_hash", hash);
if (post.containsKey("preview")) {
prop.putWiki(sb.peers.mySeed().getPublicAddress(), "mode_permission_previewmessage", message);
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_permission_previewmessage", message);
}

@ -217,7 +217,9 @@ public class Network {
final Map<String, String> response = Protocol.hello(mySeed, sb.peers.peerActions, challengeAddress, peer.hash);
if (response == null) {
Seed peerd = sb.peers.get(peer.hash);
if (peerd != null) peer = peerd;
sb.peers.peerActions.interfaceDeparture(peer, challengeIP);
prop.put("table_comment",1);
prop.put("table_comment_status", "publish: no response from peer '" + peer.getName() + "/" + post.get("peerHash") + "' from <a href=\"http://" + challengeAddress + "\" target=\"_blank\">" + challengeAddress + "</a>");
} else {

@ -30,7 +30,6 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import net.yacy.cora.document.encoding.UTF8;
import net.yacy.cora.document.feed.RSSMessage.Token;
import org.xml.sax.Attributes;
@ -100,11 +99,8 @@ public class RSSReader extends DefaultHandler {
public static RSSReader parse(final int maxsize, final byte[] a) throws IOException {
// check integrity of array
if ((a == null) || (a.length == 0)) {
throw new IOException("response=null");
}
if (a.length < 100) {
throw new IOException("response to short=" + UTF8.String(a));
if (a == null || a.length < 100) {
return null; // returning null instead of throwing an IOException is expected in most calling methods where a fail is checked against null
}
// make input stream

@ -1078,20 +1078,7 @@ public class Domains {
public static boolean isThisHostIP(final String hostName) {
if ((hostName == null) || (hostName.isEmpty())) return false;
boolean isThisHostIP = false;
try {
final InetAddress clientAddress = Domains.dnsResolve(hostName);
if (clientAddress == null) return false;
if (clientAddress.isAnyLocalAddress() || clientAddress.isLoopbackAddress()) return true;
for (final InetAddress a: myHostAddresses) {
if (a.equals(clientAddress)) {
isThisHostIP = true;
break;
}
}
} catch (final Exception e) {}
return isThisHostIP;
return isThisHostIP(Domains.dnsResolve(hostName));
}
public static boolean isThisHostIP(final InetAddress clientAddress) {

@ -201,8 +201,8 @@ public final class Cache {
public static void store(final DigestURL url, final ResponseHeader responseHeader, final byte[] file) throws IOException {
if (maxCacheSize == 0) return;
if (responseHeader.getXRobotsTag().contains("noarchive")) return; // don't cache, see http://noarchive.net/
if (responseHeader == null) throw new IOException("Cache.store of url " + url.toNormalform(false) + " not possible: responseHeader == null");
if (responseHeader.getXRobotsTag().contains("noarchive")) return; // don't cache, see http://noarchive.net/
if (file == null) throw new IOException("Cache.store of url " + url.toNormalform(false) + " not possible: file == null");
log.info("storing content of url " + url.toNormalform(false) + ", " + file.length + " bytes");

@ -185,7 +185,7 @@ public class Network
+ this.sb.peers.sizeConnected()
+ " new peer(s)");
}
publishMySeed(false);
publishMySeed();
}
// use our own formatter to prevent concurrency locks with other processes
@ -220,77 +220,36 @@ public class Network
try {
for (String ip: this.seed.getIPs()) {
this.result = Protocol.hello(Network.this.sb.peers.mySeed(), Network.this.sb.peers.peerActions, this.seed.getPublicAddress(ip), this.seed.hash);
if (this.result != null) break;
}
if ( this.result == null ) {
// no or wrong response, delete that address
final String cause = "peer ping to peer resulted in error response (added < 0)";
log.info("publish: disconnected "
+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR)
+ " peer '"
+ this.seed.getName()
+ "' from "
+ this.seed.getIPs()
+ ": "
+ cause);
Network.this.sb.peers.peerActions.peerDeparture(this.seed, cause);
} else {
if ( this.result == null ) {
// no or wrong response, delete that address
final String cause = "peer ping to peer resulted in error response (added < 0)";
log.info("publish: disconnected " + this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR) + " peer '" + this.seed.getName() + "' from " + this.seed.getIPs() + ": " + cause);
Network.this.sb.peers.peerActions.interfaceDeparture(this.seed, ip);
continue;
}
// success! we have published our peer to a senior peer
// update latest news from the other peer
log.info("publish: handshaked "
+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR)
+ " peer '"
+ this.seed.getName()
+ "' at "
+ this.seed.getIPs());
log.info("publish: handshaked "+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR) + " peer '" + this.seed.getName() + "' at " + this.seed.getIPs());
// check if seed's lastSeen has been updated
final Seed newSeed = Network.this.sb.peers.getConnected(this.seed.hash);
if ( newSeed != null ) {
if ( !newSeed.isOnline() ) {
if ( log.isFine() ) {
log.fine("publish: recently handshaked "
+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR)
+ " peer '"
+ this.seed.getName()
+ "' at "
+ this.seed.getIPs()
+ " is not online."
+ " Removing Peer from connected");
log.fine("publish: recently handshaked " + this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR) + " peer '" + this.seed.getName() + "' at " + this.seed.getIPs() + " is not online." + " Removing Peer from connected");
}
Network.this.sb.peers.peerActions.peerDeparture(newSeed, "peer not online");
Network.this.sb.peers.peerActions.interfaceDeparture(newSeed, ip);
continue;
} else if ( newSeed.getLastSeenUTC() < (System.currentTimeMillis() - 10000) ) {
// update last seed date
if ( newSeed.getLastSeenUTC() >= this.seed.getLastSeenUTC() ) {
if ( log.isFine() ) {
log
.fine("publish: recently handshaked "
+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR)
+ " peer '"
+ this.seed.getName()
+ "' at "
+ this.seed.getIPs()
+ " with old LastSeen: '"
+ my_SHORT_SECOND_FORMATTER.format(new Date(newSeed
.getLastSeenUTC())) + "'");
log.fine("publish: recently handshaked " + this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR) + " peer '" + this.seed.getName() + "' at " + this.seed.getIPs() + " with old LastSeen: '" + my_SHORT_SECOND_FORMATTER.format(new Date(newSeed.getLastSeenUTC())) + "'");
}
newSeed.setLastSeenUTC();
Network.this.sb.peers.peerActions.peerArrival(newSeed, true);
} else {
if ( log.isFine() ) {
log
.fine("publish: recently handshaked "
+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR)
+ " peer '"
+ this.seed.getName()
+ "' at "
+ this.seed.getIPs()
+ " with old LastSeen: '"
+ my_SHORT_SECOND_FORMATTER.format(new Date(newSeed
.getLastSeenUTC()))
+ "', this is more recent: '"
+ my_SHORT_SECOND_FORMATTER.format(new Date(this.seed
.getLastSeenUTC()))
+ "'");
log.fine("publish: recently handshaked " + this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR) + " peer '" + this.seed.getName() + "' at " + this.seed.getIPs() + " with old LastSeen: '" + my_SHORT_SECOND_FORMATTER.format(new Date(newSeed.getLastSeenUTC())) + "', this is more recent: '" + my_SHORT_SECOND_FORMATTER.format(new Date(this.seed.getLastSeenUTC())) + "'");
}
this.seed.setLastSeenUTC();
Network.this.sb.peers.peerActions.peerArrival(this.seed, true);
@ -298,13 +257,7 @@ public class Network
}
} else {
if ( log.isFine() ) {
log.fine("publish: recently handshaked "
+ this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR)
+ " peer '"
+ this.seed.getName()
+ "' at "
+ this.seed.getIPs()
+ " not in connectedDB");
log.fine("publish: recently handshaked " + this.seed.get(Seed.PEERTYPE, Seed.PEERTYPE_SENIOR) + " peer '" + this.seed.getName() + "' at " + this.seed.getIPs() + " not in connectedDB");
}
}
}
@ -320,7 +273,7 @@ public class Network
}
}
private boolean publishMySeed(final boolean force) {
private boolean publishMySeed() {
try {
// call this after the httpd was started up
@ -412,12 +365,13 @@ public class Network
}
i++;
final String address = seed.getPublicAddress(seed.getIP());
String ip = seed.getIP();
final String address = seed.getPublicAddress(ip);
if ( log.isFine() ) log.fine("HELLO #" + i + " to peer '" + seed.get(Seed.NAME, "") + "' at " + address); // debug
final String seederror = seed.isProper(false);
if ( (address == null) || (seederror != null) ) {
// we don't like that address, delete it
this.sb.peers.peerActions.peerDeparture(seed, "peer ping to peer resulted in address = " + address + "; seederror = " + seederror);
this.sb.peers.peerActions.interfaceDeparture(seed, ip);
sync.acquire();
} else {
// starting a new publisher thread

@ -28,7 +28,6 @@ import java.util.Map;
import net.yacy.cora.document.encoding.ASCII;
import net.yacy.cora.document.feed.RSSMessage;
import net.yacy.cora.protocol.Domains;
import net.yacy.cora.storage.ConcurrentARC;
import net.yacy.kelondro.util.MapTools;
import net.yacy.peers.operation.yacyVersion;
@ -83,7 +82,7 @@ public class PeerActions {
return false;
}
final Seed doubleSeed = this.seedDB.lookupByIP(Domains.dnsResolve(seed.getIP()), seed.getPort(), true, false, false);
final Seed doubleSeed = this.seedDB.lookupByIPs(seed.getIPs(), seed.getPort(), true, false, false);
if ((doubleSeed != null) && (doubleSeed.getPort() == seed.getPort()) && (!(doubleSeed.hash.equals(seed.hash)))) {
// a user frauds with his peer different peer hashes
if (Network.log.isFine()) Network.log.fine("connect: rejecting FRAUD (double hashes " + doubleSeed.hash + "/" + seed.hash + " on same port " + seed.getPort() + ") peer " + seed.getName());
@ -179,7 +178,7 @@ public class PeerActions {
}
// the seed is new
if ((this.seedDB.mySeedIsDefined()) && (seed.getIP().equals(this.seedDB.mySeed().getIP()))) {
if ((this.seedDB.mySeedIsDefined()) && (seed.clash(this.seedDB.mySeed().getIPs()))) {
// seed from the same IP as the calling client: can be
// the case if there runs another one over a NAT
if (Network.log.isFine()) Network.log.fine("connect: saved NEW seed (myself IP) " + seed.getIPs());
@ -202,6 +201,44 @@ public class PeerActions {
return res;
}
/**
* If any of the peer2peer communication attempts fail, then remove the tested IP from the peer by calling this method.
* if the given IP is the only one which is remaining, then the IP is NOT removed from the peer but the peer is removed from the
* active list of peers instead. That means when a peer arrives in the deactivated peer list, then it has at least one IP left
* which should be actually the latest IP where the peer was accessible.
* @param peer
* @param ip
*/
public void interfaceDeparture(final Seed peer, String ip) {
if (peer == null) return;
if (Network.log.isFine()) Network.log.fine("connect: no contact to a interface from " + peer.get(Seed.PEERTYPE, Seed.PEERTYPE_VIRGIN) + " peer '" + peer.getName() + "' at " + ip);
synchronized (this.seedDB) {
if (this.seedDB.hasConnected(ASCII.getBytes(peer.hash))) {
if (peer.countIPs() > 1) {
if (peer.removeIP(ip)) {
this.seedDB.updateConnected(peer);
} else {
// this is bad because the IP does not appear at all in the seed. We consider the seed as poisoned and remove it from the active peers
this.seedDB.addDisconnected(peer);
}
} else {
// disconnect the peer anyway
if (!this.seedDB.hasDisconnected(ASCII.getBytes(peer.hash))) { this.disconnects++; }
peer.put(Seed.DCT, Long.toString(System.currentTimeMillis()));
this.seedDB.addDisconnected(peer);
}
}
}
EventChannel.channels(EventChannel.PEERNEWS).addMessage(new RSSMessage(peer.getName() + " interface not available: " + ip, "", ""));
}
/**
* PeerDeparture marks a peers as not available. Because with IPv6 we have more than one IP, we first mark single IPs as not available instead of marking the whole peer.
* Therefore this method is deprecated. Please use interfaceDeparture instead.
* @param peer
* @param cause
*/
@Deprecated
public void peerDeparture(final Seed peer, final String cause) {
if (peer == null) return;
// we do this if we did not get contact with the other peer

@ -57,6 +57,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
@ -129,29 +130,37 @@ import org.apache.solr.common.SolrInputDocument;
public final class Protocol {
@Deprecated
private static byte[] postToFile(
final SeedDB seedDB,
final String targetHash,
final String filename,
final Map<String, ContentBody> parts,
final int timeout) throws IOException {
return postToFile(seedDB.targetAddress(targetHash), targetHash, filename, parts, timeout);
}
/**
* wrapper class for multi-post attempts to multiple IPs
*/
private static class Post {
public byte[] result; // contains the result from a successful post or null if no attempt was successful
public Set<String> unsuccessfulAddresses; // contains a set of addresses which had been tested for submission was without success
public String successfulAddress; // contains the address which had been successfully used or null if no success with any Address
public Post(
final String targetAddress,
final String targetPeerHash,
final String path,
final Map<String, ContentBody> parts,
final int timeout) throws IOException {
final HTTPClient httpClient = new HTTPClient(ClientIdentification.yacyInternetCrawlerAgent);
httpClient.setTimout(timeout);
this.result = httpClient.POSTbytes(
new MultiProtocolURL("http://" + targetAddress + path),
Seed.b64Hash2hexHash(targetPeerHash) + ".yacyh",
parts,
false, true);
this.unsuccessfulAddresses = new HashSet<>();
if (this.result == null) {
this.unsuccessfulAddresses.add(targetAddress);
this.successfulAddress = null;
} else {
this.successfulAddress = targetAddress;
}
}
private static byte[] postToFile(
final String targetAddress,
final String targetPeerHash,
final String filename,
final Map<String, ContentBody> parts,
final int timeout) throws IOException {
final HTTPClient httpClient = new HTTPClient(ClientIdentification.yacyInternetCrawlerAgent);
httpClient.setTimout(timeout);
return httpClient.POSTbytes(
new MultiProtocolURL("http://" + targetAddress + "/yacy/" + filename),
Seed.b64Hash2hexHash(targetPeerHash) + ".yacyh",
parts,
false, true);
}
/**
@ -197,10 +206,7 @@ public final class Protocol {
responseTime = System.currentTimeMillis() - start;
result = FileUtils.table(content);
} catch (final Exception e ) {
if ( Thread.currentThread().isInterrupted() ) {
Network.log.info("yacyClient.hello thread '"
+ Thread.currentThread().getName()
+ "' interrupted.");
if ( Thread.currentThread().isInterrupted() ) {Network.log.info("yacyClient.hello thread '" + Thread.currentThread().getName() + "' interrupted.");
return null;
}
Network.log.info("yacyClient.hello thread '" + Thread.currentThread().getName() + "', peer " + targetAddress + "; exception: " + e.getMessage());
@ -360,8 +366,8 @@ public final class Protocol {
basicRequestParts(Switchboard.getSwitchboard(), target.hash, salt);
parts.put("object", UTF8.StringBody("seed"));
parts.put("env", UTF8.StringBody(seedHash));
final byte[] content = postToFile(target.getPublicAddress(target.getIP()), target.hash, "query.html", parts, 10000);
final Map<String, String> result = FileUtils.table(content);
final Post post = new Post(target.getPublicAddress(target.getIP()), target.hash, "/yacy/query.html", parts, 10000);
final Map<String, String> result = FileUtils.table(post.result);
if ( result == null || result.isEmpty() ) {
return null;
@ -385,9 +391,9 @@ public final class Protocol {
parts.put("ttl", UTF8.StringBody("0"));
parts.put("env", UTF8.StringBody(""));
ConcurrentLog.info("**hello-DEBUG**queryRWICount**", "posting request to " + targetAddress);
final byte[] content = postToFile(targetAddress, targetHash, "query.html", parts, timeout);
ConcurrentLog.info("**hello-DEBUG**queryRWICount**", "received CONTENT from requesting " + targetAddress + (content == null ? "NULL" : (": length = " + content.length)));
final Map<String, String> result = FileUtils.table(content);
final Post post = new Post(targetAddress, targetHash, "/yacy/query.html", parts, timeout);
ConcurrentLog.info("**hello-DEBUG**queryRWICount**", "received CONTENT from requesting " + targetAddress + (post.result == null ? "NULL" : (": length = " + post.result.length)));
final Map<String, String> result = FileUtils.table(post.result);
if (result == null || result.isEmpty()) return new long[] {-1, -1};
ConcurrentLog.info("**hello-DEBUG**queryRWICount**", "received RESULT from requesting " + targetAddress + " : result = " + result.toString());
final String resp = result.get("response");
@ -436,38 +442,32 @@ public final class Protocol {
parts.put("time", UTF8.StringBody(Long.toString(maxTime)));
// final byte[] result = HTTPConnector.getConnector(MultiProtocolURI.yacybotUserAgent).post(new MultiProtocolURI("http://" + target.getClusterAddress() + "/yacy/urls.xml"), (int) maxTime, target.getHexHash() + ".yacyh", parts);
final HTTPClient httpClient = new HTTPClient(ClientIdentification.yacyInternetCrawlerAgent, (int) maxTime);
final byte[] result = httpClient.POSTbytes(new MultiProtocolURL("http://" + target.getPublicAddress(target.getIP()) + "/yacy/urls.xml"), target.getHexHash() + ".yacyh", parts, false, true);
String ip = target.getIP();
final byte[] result = httpClient.POSTbytes(new MultiProtocolURL("http://" + target.getPublicAddress(ip) + "/yacy/urls.xml"), target.getHexHash() + ".yacyh", parts, false, true);
final RSSReader reader = RSSReader.parse(RSSFeed.DEFAULT_MAXSIZE, result);
if ( reader == null ) {
Network.log.warn("yacyClient.queryRemoteCrawlURLs failed asking peer '"
+ target.getName()
+ "': probably bad response from remote peer (1), reader == null");
Network.log.warn("yacyClient.queryRemoteCrawlURLs failed asking peer '" + target.getName() + "': probably bad response from remote peer (1), reader == null");
target.put(Seed.RCOUNT, "0");
seedDB.update(target.hash, target); // overwrite number of remote-available number to avoid that this peer is called again (until update is done by peer ping)
seedDB.peerActions.interfaceDeparture(target, ip);
//Log.logException(e);
return null;
}
final RSSFeed feed = reader.getFeed();
if ( feed == null ) {
// case where the rss reader does not understand the content
Network.log.warn("yacyClient.queryRemoteCrawlURLs failed asking peer '"
+ target.getName()
+ "': probably bad response from remote peer (2)");
Network.log.warn("yacyClient.queryRemoteCrawlURLs failed asking peer '" + target.getName() + "': probably bad response from remote peer (2)");
//System.out.println("***DEBUG*** rss input = " + UTF8.String(result));
target.put(Seed.RCOUNT, "0");
seedDB.update(target.hash, target); // overwrite number of remote-available number to avoid that this peer is called again (until update is done by peer ping)
seedDB.updateConnected(target); // overwrite number of remote-available number to avoid that this peer is called again (until update is done by peer ping)
//Log.logException(e);
return null;
}
// update number of remotely available links in seed
target.put(Seed.RCOUNT, Integer.toString(Math.max(0, targetCount - feed.size())));
seedDB.update(target.hash, target);
seedDB.updateConnected(target);
return feed;
} catch (final IOException e ) {
Network.log.warn("yacyClient.queryRemoteCrawlURLs error asking peer '"
+ target.getName()
+ "':"
+ e.toString());
Network.log.warn("yacyClient.queryRemoteCrawlURLs error asking peer '" + target.getName() + "':" + e.toString());
return null;
}
}
@ -1117,8 +1117,8 @@ public final class Protocol {
return dls;
}
public static Map<String, String> permissionMessage(final SeedDB seedDB, final String targetHash) {
// ask for allowed message size and attachement size
public static Map<String, String> permissionMessage(final String targetAddress, final String targetHash) {
// ask for allowed message size and attachment size
// if this replies null, the peer does not answer
// prepare request
@ -1129,8 +1129,8 @@ public final class Protocol {
final Map<String, ContentBody> parts =
basicRequestParts(Switchboard.getSwitchboard(), targetHash, salt);
parts.put("process", UTF8.StringBody("permission"));
final byte[] content = postToFile(seedDB, targetHash, "message.html", parts, 6000);
final Map<String, String> result = FileUtils.table(content);
final Post post = new Post(targetAddress, targetAddress, "/yacy/message.html", parts, 6000);
final Map<String, String> result = FileUtils.table(post.result);
return result;
} catch (final Exception e ) {
// most probably a network time-out exception
@ -1157,8 +1157,8 @@ public final class Protocol {
parts.put("myseed", UTF8.StringBody(seedDB.mySeed().genSeedStr(salt)));
parts.put("subject", UTF8.StringBody(subject));
parts.put("message", UTF8.StringBody(message));
final byte[] content = postToFile(seedDB, targetHash, "message.html", parts, 20000);
final Map<String, String> result = FileUtils.table(content);
final Post post = new Post(seedDB.targetAddress(targetHash), targetHash, "/yacy/message.html", parts, 20000);
final Map<String, String> result = FileUtils.table(post.result);
return result;
} catch (final Exception e ) {
Network.log.warn("yacyClient.postMessage error:" + e.getMessage());
@ -1312,13 +1312,7 @@ public final class Protocol {
return null;
} // all url's known
EventChannel
.channels(EventChannel.DHTSEND)
.addMessage(
new RSSMessage(
"Sent " + indexes.size() + " RWIs " + indexes.toString() + " to " + targetSeed.getName() + "/[" + targetSeed.hash + "], " + uhs.length + " URLs there unknown",
"",
targetSeed.hash));
EventChannel.channels(EventChannel.DHTSEND).addMessage(new RSSMessage("Sent " + indexes.size() + " RWIs " + indexes.toString() + " to " + targetSeed.getName() + "/[" + targetSeed.hash + "], " + uhs.length + " URLs there unknown", "", targetSeed.hash));
in = transferURL(targetSeed, uhs, urlRefs, segment, gzipBody, timeout);
@ -1352,7 +1346,8 @@ public final class Protocol {
final ReferenceContainerCache<WordReference> indexes,
boolean gzipBody,
final int timeout) {
final String address = targetSeed.getPublicAddress(targetSeed.getIP());
String ip = targetSeed.getIP();
final String address = targetSeed.getPublicAddress(ip);
if ( address == null ) {
Network.log.warn("no address for transferRWI");
return null;
@ -1390,8 +1385,7 @@ public final class Protocol {
return result;
}
try {
final Map<String, ContentBody> parts =
basicRequestParts(Switchboard.getSwitchboard(), targetSeed.hash, salt);
final Map<String, ContentBody> parts = basicRequestParts(Switchboard.getSwitchboard(), targetSeed.hash, salt);
parts.put("wordc", UTF8.StringBody(Integer.toString(indexes.size())));
parts.put("entryc", UTF8.StringBody(Integer.toString(indexcount)));
parts.put("indexes", UTF8.StringBody(entrypost.toString()));
@ -1424,7 +1418,8 @@ public final class Protocol {
boolean gzipBody,
final int timeout) {
// this post a message to the remote message board
final String address = targetSeed.getPublicAddress(targetSeed.getIP());
String ip = targetSeed.getIP();
final String address = targetSeed.getPublicAddress(ip);
if ( address == null ) {
return null;
}
@ -1536,13 +1531,13 @@ public final class Protocol {
final Map<String, ContentBody> parts =
basicRequestParts(Switchboard.getSwitchboard(), target.hash, salt);
parts.put("object", UTF8.StringBody("host"));
final byte[] content = postToFile(target.getPublicAddress(target.getIP()), target.hash, "idx.json", parts, 30000);
if ( content == null || content.length == 0 ) {
final Post post = new Post(target.getPublicAddress(target.getIP()), target.hash, "/yacy/idx.json", parts, 30000);
if ( post.result == null || post.result.length == 0 ) {
Network.log.warn("yacyClient.loadIDXHosts error: empty result");
return null;
}
final JSONObject json =
new JSONObject(new JSONTokener(new InputStreamReader(new ByteArrayInputStream(content))));
new JSONObject(new JSONTokener(new InputStreamReader(new ByteArrayInputStream(post.result))));
/* the json has the following form:
{
"version":"#[version]#",

@ -389,11 +389,65 @@ public class Seed implements Cloneable, Comparable<Seed>, Comparator<Seed>
return h;
}
/**
* count the number of IPs assgined to that peer
* @return the number of peers in field IP (should be 1 all the time) plus the number of IPs in the IP6 field.
*/
public final int countIPs() {
final String ipx = this.dna.get(Seed.IP); // may contain both, IPv4 or IPv6
final String ip6 = this.dna.get(Seed.IP6);
Set<String> ip6s = MapTools.string2set(ip6, "|");
if (ip6s == null || ip6s.size() == 0) {
return (ipx == null || ipx.isEmpty()) ? 0 : 1;
}
return (ipx == null || ipx.isEmpty()) ? ip6s.size() : ip6s.size() + 1;
}
/**
* remove the given IP from the seed. Be careful not to remove the last IP; maybe call countIPs before calling the method.
* @param ip
* @return true if the IP was in the seed and had been removed. If the peer did not change, this returns false.
*/
public final boolean removeIP(String ip) {
String ipx = chopZoneID(this.dna.get(Seed.IP)); // may contain both, IPv4 or IPv6
final String ip6 = this.dna.get(Seed.IP6);
Set<String> ip6s = MapTools.string2set(ip6, "|");
Iterator<String> i = ip6s.iterator();
while (i.hasNext()) {String x = i.next(); if (x.indexOf('%') >= 0) i.remove();}
if (ip6s == null || ip6s.size() == 0) {
if (ipx != null && !ipx.isEmpty() && ipx.equals(ip)) {
this.dna.put(Seed.IP, ""); // DON'T DO THAT! (the line is correct but you should not remove the last IP
return true;
}
return false;
}
if (ip6s != null && ip6s.contains(ip)) {
ip6s.remove(ip);
this.dna.put(Seed.IP6, MapTools.set2string(ip6s, "|", false));
return true;
}
if (ipx != null && !ipx.isEmpty() && ipx.equals(ip)) {
ipx = ip6s.iterator().next();
this.dna.put(Seed.IP, chopZoneID(ipx));
ip6s.remove(ipx);
this.dna.put(Seed.IP6, MapTools.set2string(ip6s, "|", false));
return true;
}
return false;
}
private String chopZoneID(String ip) {
int i = ip.indexOf('%');
return i < 0 ? ip : ip.substring(0, i);
}
/**
* clash tests if any of the given ips are also contained in the Seeds ip set
* @param ips
* @return true if any of the given IPs are identical to the Seeds IP set
*/
public boolean clash(Set<String> ips) {
Set<String> myIPs = getIPs();
for (String s: ips) {
@ -509,7 +563,8 @@ public class Seed implements Cloneable, Comparable<Seed>, Comparator<Seed>
* ATTENTION: if the given IP is IPv6, then after the call that IP is the only one assigned to the peer!
* @param ip
*/
public final void setIP(final String ip) {
public final void setIP(String ip) {
ip = chopZoneID(ip);
if (!isProperIP(ip)) return;
String oldIP = this.dna.get(Seed.IP);
String oldIP6 = this.dna.get(Seed.IP6);
@ -544,7 +599,7 @@ public class Seed implements Cloneable, Comparable<Seed>, Comparator<Seed>
this.dna.put(Seed.IP6, MapTools.set2string(ipv6, "|", false));
}
} else {
this.dna.put(Seed.IP, ipv4.iterator().next());
this.dna.put(Seed.IP, chopZoneID(ipv4.iterator().next()));
this.dna.put(Seed.IP6, MapTools.set2string(ipv6, "|", false));
}
}

@ -601,21 +601,41 @@ public final class SeedDB implements AlternativeDomainNames {
return seed;
}
public void update(final String hash, final Seed seed) {
if (this.mySeed == null) initMySeed();
if (hash.equals(this.mySeed.hash)) {
this.mySeed = seed;
return;
public void updateConnected(final Seed seed) {
if (seed.isProper(false) != null) return;
final ConcurrentMap<String, String> seedPropMap = seed.getMap();
synchronized (this) {
if (this.seedActiveDB.containsKey(ASCII.getBytes(seed.hash))) try {
this.seedActiveDB.insert(ASCII.getBytes(seed.hash), seedPropMap);
} catch (final Exception e) {
Network.log.severe("ERROR add: seed.db corrupt (" + e.getMessage() + "); resetting seed.db", e);
resetActiveTable();
}
}
}
public void updateDisconnected(final Seed seed) {
if (seed.isProper(false) != null) return;
final ConcurrentMap<String, String> seedPropMap = seed.getMap();
synchronized (this) {
if (this.seedPassiveDB.containsKey(ASCII.getBytes(seed.hash))) try {
this.seedPassiveDB.insert(ASCII.getBytes(seed.hash), seedPropMap);
} catch (final Exception e) {
Network.log.severe("ERROR add: seed.db corrupt (" + e.getMessage() + "); resetting seed.db", e);
resetActiveTable();
}
}
}
public void updatePotential(final Seed seed) {
if (seed.isProper(false) != null) return;
final ConcurrentMap<String, String> seedPropMap = seed.getMap();
synchronized (this) {
if (this.seedPotentialDB.containsKey(ASCII.getBytes(seed.hash))) try {
this.seedPotentialDB.insert(ASCII.getBytes(seed.hash), seedPropMap);
} catch (final Exception e) {
Network.log.severe("ERROR add: seed.db corrupt (" + e.getMessage() + "); resetting seed.db", e);
resetActiveTable();
}
}
final byte[] hashb = ASCII.getBytes(hash);
Seed s = get(hash, this.seedActiveDB);
if (s != null) try { this.seedActiveDB.insert(hashb, seed.getMap()); return;} catch (final Exception e) {ConcurrentLog.logException(e);}
s = get(hash, this.seedPassiveDB);
if (s != null) try { this.seedPassiveDB.insert(hashb, seed.getMap()); return;} catch (final Exception e) {ConcurrentLog.logException(e);}
s = get(hash, this.seedPotentialDB);
if (s != null) try { this.seedPotentialDB.insert(hashb, seed.getMap()); return;} catch (final Exception e) {ConcurrentLog.logException(e);}
}
public Seed lookupByName(String peerName) {
@ -662,6 +682,20 @@ public final class SeedDB implements AlternativeDomainNames {
return null;
}
public Seed lookupByIPs(
final Set<String> peerIPs,
final int port, /* port may be -1 if not significant */
final boolean lookupConnected,
final boolean lookupDisconnected,
final boolean lookupPotential
) {
for (String i: peerIPs) {
Seed s = lookupByIP(Domains.dnsResolve(i), port, lookupConnected, lookupDisconnected, lookupPotential);
if (s != null) return s;
}
return null;
}
public Seed lookupByIP(
final InetAddress peerIP,
final int port, /* port may be -1 if not significant */

@ -270,7 +270,7 @@ public class Transmission {
if (newTarget != null) {
if (this.dhtTarget.clash(newTarget.getIPs())) {
newTarget.setFlagAcceptRemoteIndex(false);
Transmission.this.seeds.update(newTarget.hash, newTarget);
Transmission.this.seeds.updateConnected(newTarget);
} else {
// we tried an old Address. Don't change anything
}

@ -44,7 +44,6 @@ import net.yacy.cora.protocol.RequestHeader;
import net.yacy.cora.protocol.ResponseHeader;
import net.yacy.cora.util.ByteBuffer;
import net.yacy.cora.util.ConcurrentLog;
import net.yacy.cora.util.NumberTools;
import net.yacy.kelondro.util.FileUtils;
import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants;

Loading…
Cancel
Save