Author: toad
Date: 2007-09-21 18:12:53 +0000 (Fri, 21 Sep 2007)
New Revision: 15245
Modified:
trunk/freenet/src/freenet/node/FNPPacketMangler.java
trunk/freenet/src/freenet/node/OpennetManager.java
Log:
Keep the last 50 dropped opennet nodes in RAM. Reconnect if we are desperate
for nodes and if they try to connect to us.
Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java 2007-09-21
18:06:01 UTC (rev 15244)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java 2007-09-21
18:12:53 UTC (rev 15245)
@@ -130,7 +130,7 @@
}
if(length > Node.SYMMETRIC_KEY_LENGTH /* iv */ + HASH_LENGTH + 2
&& !node.isStopping()) {
// Might be an auth packet
- if(tryProcessAuth(buf, offset, length, opn, peer)) return;
+ if(tryProcessAuth(buf, offset, length, opn, peer, false))
return;
}
}
PeerNode[] peers = crypto.getPeerNodes();
@@ -160,9 +160,21 @@
for(int i=0;i<peers.length;i++) {
pn = peers[i];
if(pn == opn) continue;
- if(tryProcessAuth(buf, offset, length, pn, peer)) return;
+ if(tryProcessAuth(buf, offset, length, pn, peer, false))
return;
}
}
+ OpennetManager opennet = node.getOpennet();
+ if(opennet != null) {
+ // Try old opennet connections.
+ if(opennet.wantPeer(null, false)) {
+ // We want a peer.
+ // Try old connections.
+ PeerNode[] oldPeers = opennet.getOldPeers();
+ for(int i=0;i<oldPeers.length;i++) {
+ if(tryProcessAuth(buf, offset, length,
oldPeers[i], peer, true)) return;
+ }
+ }
+ }
Logger.normal(this,"Unmatchable packet from "+peer);
}
@@ -175,7 +187,7 @@
* @param peer The Peer to send a reply to
* @return True if we handled a negotiation packet, false otherwise.
*/
- private boolean tryProcessAuth(byte[] buf, int offset, int length,
PeerNode opn, Peer peer) {
+ private boolean tryProcessAuth(byte[] buf, int offset, int length,
PeerNode opn, Peer peer, boolean oldOpennetPeer) {
BlockCipher authKey = opn.incomingSetupCipher;
if(logMINOR) Logger.minor(this, "Decrypt key:
"+HexUtil.bytesToHex(opn.incomingSetupKey)+" for "+peer+" : "+opn+" in
tryProcessAuth");
// Does the packet match IV E( H(data) data ) ?
@@ -219,7 +231,7 @@
if(Arrays.equals(realHash, hash)) {
// Got one
- processDecryptedAuth(payload, opn, peer);
+ processDecryptedAuth(payload, opn, peer, oldOpennetPeer);
opn.reportIncomingBytes(length);
return true;
} else {
@@ -232,7 +244,7 @@
* Process a decrypted, authenticated auth packet.
* @param payload The packet payload, after it has been decrypted.
*/
- private void processDecryptedAuth(byte[] payload, PeerNode pn, Peer
replyTo) {
+ private void processDecryptedAuth(byte[] payload, PeerNode pn, Peer
replyTo, boolean oldOpennetPeer) {
if(logMINOR) Logger.minor(this, "Processing decrypted auth packet from
"+replyTo+" for "+pn);
if(pn.isDisabled()) {
if(logMINOR) Logger.minor(this, "Won't connect to a disabled
peer ("+pn+ ')');
@@ -313,10 +325,10 @@
// Verify the packet, then complete
// Format: IV E_K ( H(data) data )
// Where data = [ long: bob's startup number ]
- processSignedDHTwoOrThree(2, payload, pn, replyTo,
true);
+ processSignedDHTwoOrThree(2, payload, pn, replyTo,
true, oldOpennetPeer);
} else if(packetType == 3) {
// We are Alice
- processSignedDHTwoOrThree(3, payload, pn, replyTo,
false);
+ processSignedDHTwoOrThree(3, payload, pn, replyTo,
false, oldOpennetPeer);
}
}else {
Logger.error(this, "Decrypted auth packet but unknown negotiation
type "+negType+" from "+replyTo+" possibly from "+pn);
@@ -492,8 +504,11 @@
* Data
*
* May decrypt in place.
+ * @param oldOpennetPeer If true, the peer we are negotiating with is not
in
+ * the primary routing table, it needs to be promoted from the list of old
opennet
+ * nodes.
*/
- private DiffieHellmanContext processSignedDHTwoOrThree(int phase, byte[]
payload, PeerNode pn, Peer replyTo, boolean sendCompletion) {
+ private DiffieHellmanContext processSignedDHTwoOrThree(int phase, byte[]
payload, PeerNode pn, Peer replyTo, boolean sendCompletion, boolean
oldOpennetPeer) {
if(logMINOR) Logger.minor(this, "Handling signed stage "+phase+" auth
packet");
// Get context, cipher, IV
DiffieHellmanContext ctx = (DiffieHellmanContext)
pn.getKeyAgreementSchemeContext();
@@ -551,6 +566,11 @@
// Success!
long bootID = Fields.bytesToLong(data);
+
+ // Promote if necessary
+ if(oldOpennetPeer)
+ node.peers.addPeer(pn);
+
// Send the completion before parsing the data, because this is easiest
// Doesn't really matter - if it fails, we get loads of errors
anyway...
// Only downside is that the other side might still think we are
connected for a while.
Modified: trunk/freenet/src/freenet/node/OpennetManager.java
===================================================================
--- trunk/freenet/src/freenet/node/OpennetManager.java 2007-09-21 18:06:01 UTC
(rev 15244)
+++ trunk/freenet/src/freenet/node/OpennetManager.java 2007-09-21 18:12:53 UTC
(rev 15245)
@@ -37,6 +37,11 @@
/** Our peers. PeerNode's are promoted when they successfully fetch a
key. Normally we take
* the bottom peer, but if that isn't eligible to be dropped, we
iterate up the list. */
private final LRUQueue peersLRU;
+ /** Old peers. Opennet peers which we dropped but would still like to
talk to
+ * if we have no other option. */
+ private final LRUQueue oldPeers;
+ /** Maximum number of old peers */
+ static final int MAX_OLD_PEERS = 50;
/** Time at which last dropped a peer */
private long timeLastDropped;
/** Number of successful CHK requests since last added a node */
@@ -86,6 +91,7 @@
}
}
peersLRU = new LRUQueue();
+ oldPeers = new LRUQueue();
node.peers.tryReadPeers(new File(node.nodeDir,
"openpeers-"+crypto.portNumber).toString(), crypto, this, true);
OpennetPeerNode[] nodes = node.peers.getOpennetPeers();
Arrays.sort(nodes, new Comparator() {
@@ -373,8 +379,18 @@
node.peers.disconnect(pn, true, false);
}
- public synchronized void onRemove(OpennetPeerNode pn) {
+ public void onRemove(OpennetPeerNode pn) {
+ synchronized(this) {
peersLRU.remove(pn);
+ oldPeers.push(pn);
+ while(oldPeers.size() > MAX_OLD_PEERS)
+ oldPeers.pop();
+ }
+ pn.disconnected();
}
+ public synchronized PeerNode[] getOldPeers() {
+ return (PeerNode[]) oldPeers.toArray(new
PeerNode[oldPeers.size()]);
+ }
+
}