Author: toad
Date: 2006-01-31 01:47:58 +0000 (Tue, 31 Jan 2006)
New Revision: 7966
Modified:
trunk/freenet/src/freenet/io/comm/Peer.java
trunk/freenet/src/freenet/node/FNPPacketMangler.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/PeerNode.java
trunk/freenet/src/freenet/node/TextModeClientInterface.java
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/support/SimpleFieldSet.java
Log:
417:
Multi-homing infrastructure.
Actual true multi-homing doesn't work yet; you will need to fix
Node.exportFieldSet().
True multi-homing is *not* a priority.
But what is important is this: proper dyndns support.
If you specify a DNS name on the command line, it will be preserved.
Even if we detect an alternate IP address, in which case we will try to connect
to both.
This should help a lot with some folk on dynamic IP addresses.
Obviously dyndns is not the best option, but it is an easy option, and if it's
present, it always works.
Most of this was done by nextgens; I just debugged it a bit and tidied it
up/completed it.
Modified: trunk/freenet/src/freenet/io/comm/Peer.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/Peer.java 2006-01-31 01:03:51 UTC (rev
7965)
+++ trunk/freenet/src/freenet/io/comm/Peer.java 2006-01-31 01:47:58 UTC (rev
7966)
@@ -73,7 +73,7 @@
throw new PeerParseException(e);
}
}
-
+
public boolean isNull() {
return _port == 0;
}
@@ -110,11 +110,21 @@
}
public String toString() {
- return (_address != null ? _address.getHostAddress() : "null")
+ ":" + _port;
+ return (_address != null ? getHostName(_address) : "null") +
":" + _port;
}
public void writeToDataOutputStream(DataOutputStream dos) throws
IOException {
dos.write(_address.getAddress());
dos.writeInt(_port);
}
+
+ /**
+ * Return the hostname or the IP address of the given InetAddress.
+ * Does not attempt to do a reverse lookup; if the hostname is
+ * known, return it, otherwise return the textual IP address.
+ */
+ public static String getHostName(InetAddress primaryIPAddress) {
+ String s = primaryIPAddress.toString();
+ return s.substring(0, s.indexOf('/')).trim();
+ }
}
\ No newline at end of file
Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java 2006-01-31
01:03:51 UTC (rev 7965)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java 2006-01-31
01:47:58 UTC (rev 7966)
@@ -1281,8 +1281,11 @@
pn.setDHContext(ctx);
}
}
- sendFirstHalfDHPacket(0, ctx.getOurExponential(), pn, pn.getPeer());
- pn.sentHandshake();
+
+ for(int i=0;i<pn.getHandshakeIPs().length;i++){
+ sendFirstHalfDHPacket(0, ctx.getOurExponential(), pn,
pn.getHandshakeIPs()[i]);
+ pn.sentHandshake();
+ }
}
public boolean isDisconnected(PeerContext context) {
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-01-31 01:03:51 UTC (rev
7965)
+++ trunk/freenet/src/freenet/node/Node.java 2006-01-31 01:47:58 UTC (rev
7966)
@@ -908,7 +908,7 @@
*/
public SimpleFieldSet exportFieldSet() {
SimpleFieldSet fs = new SimpleFieldSet();
- fs.put("physical.udp",
getPrimaryIPAddress().getHostAddress()+":"+portNumber);
+ fs.put("physical.udp",
Peer.getHostName(getPrimaryIPAddress())+":"+portNumber);
fs.put("identity", HexUtil.bytesToHex(myIdentity));
fs.put("location", Double.toString(lm.getLocation().getValue()));
fs.put("version", Version.getVersionString());
Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java 2006-01-31 01:03:51 UTC
(rev 7965)
+++ trunk/freenet/src/freenet/node/PeerNode.java 2006-01-31 01:47:58 UTC
(rev 7966)
@@ -12,6 +12,7 @@
import java.util.LinkedList;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
+import java.util.Vector;
import freenet.crypt.BlockCipher;
import freenet.crypt.DiffieHellmanContext;
@@ -52,8 +53,11 @@
static boolean disableProbabilisticHTLs = false;
/** My low-level address for SocketManager purposes */
- private Peer peer;
+ private Peer detectedPeer;
+ /** Advertised addresses */
+ private Vector nominalPeer;
+
/** Is this a testnet node? */
public final boolean testnetEnabled;
@@ -191,16 +195,35 @@
String locationString = fs.get("location");
if(locationString == null) throw new FSParseException("No location");
currentLocation = new Location(locationString);
- String physical = fs.get("physical.udp");
- if(physical == null) throw new FSParseException("No physical.udp");
- peer = new Peer(physical);
+
+ if(nominalPeer==null)
+ nominalPeer=new Vector();
+ nominalPeer.removeAllElements();
+ try{
+ String physical[]=fs.getAll("physical.udp");
+ if(physical==null){
+ Peer p = new Peer(fs.get("physical.udp"));
+ nominalPeer.addElement(p);
+ }else{
+ for(int i=0;i<physical.length;i++){
+ Peer p = new Peer(physical[i]);
+ if(!nominalPeer.contains(p))
+ nominalPeer.addElement(p);
+ }
+ }
+ } catch (Exception e1) {
+ throw new FSParseException(e1);
+ }
+ if(nominalPeer.isEmpty()) throw new FSParseException("No
physical.udp");
+ detectedPeer=(Peer) nominalPeer.firstElement();
+
String name = fs.get("myName");
if(name == null) throw new FSParseException("No name");
myName = name;
String testnet = fs.get("testnet");
testnetEnabled = testnet == null ? false :
(testnet.equalsIgnoreCase("true") || testnet.equalsIgnoreCase("yes"));
if(testnetEnabled != node.testnetEnabled) {
- String err = "Ignoring incompatible node "+peer+" -
peer.testnet="+testnetEnabled+"("+testnet+") but
node.testnet="+node.testnetEnabled;
+ String err = "Ignoring incompatible node "+detectedPeer+" -
peer.testnet="+testnetEnabled+"("+testnet+") but
node.testnet="+node.testnetEnabled;
Logger.error(this, err);
throw new PeerParseException(err);
}
@@ -267,11 +290,32 @@
/**
* Get my low-level address
*/
- public Peer getPeer() {
- return peer;
+ public Peer getDetectedPeer() {
+ return detectedPeer;
}
+
+ public Peer getPeer(){
+ return detectedPeer;
+ }
/**
+ * Returns an array with the advertised addresses and the detected one
+ */
+ public Peer[] getHandshakeIPs(){
+ Peer[] p=null;
+
+ if( ! nominalPeer.contains(detectedPeer)){
+ p= new Peer[1+nominalPeer.size()];
+ p[0]=detectedPeer;
+ for(int i=1;i<nominalPeer.size()+1;i++)
+ p[i]=(Peer) nominalPeer.get(i);
+ }else{
+ return (Peer[]) nominalPeer.toArray(new
Peer[nominalPeer.size()]);
+ }
+ return p;
+ }
+
+ /**
* What is my current keyspace location?
*/
public Location getLocation() {
@@ -519,7 +563,7 @@
* @param newPeer The new address of the peer.
*/
public void changedIP(Peer newPeer) {
- this.peer = newPeer;
+ this.detectedPeer=newPeer;
}
/**
@@ -551,7 +595,7 @@
* @return short version of toString()
*/
public String shortToString() {
- return
super.toString()+"@"+peer.toString()+"@"+HexUtil.bytesToHex(identity);
+ return
super.toString()+"@"+detectedPeer.toString()+"@"+HexUtil.bytesToHex(identity);
}
public String toString() {
@@ -794,15 +838,29 @@
Location loc = new Location(locationString);
if(!loc.equals(currentLocation)) changedAnything = true;
currentLocation = loc;
- String physical = fs.get("physical.udp");
- if(physical == null) throw new FSParseException("No physical.udp");
- try {
- Peer p = new Peer(physical);
- if(!p.equals(peer)) changedAnything = true;
- peer = p;
- } catch (PeerParseException e1) {
- throw new FSParseException(e1);
+
+ if(nominalPeer==null)
+ nominalPeer=new Vector();
+ nominalPeer.removeAllElements();
+ try{
+ String physical[]=fs.getAll("physical.udp");
+ if(physical==null){
+ Peer p = new Peer(fs.get("physical.udp"));
+ nominalPeer.addElement(p);
+ }else{
+ for(int i=0;i<physical.length;i++){
+ Peer p = new Peer(physical[i]);
+ if(!nominalPeer.contains(p))
+ nominalPeer.addElement(p);
+ }
+ }
+ } catch (Exception e1) {
+ throw new FSParseException(e1);
}
+ if(nominalPeer.isEmpty()) throw new FSParseException("No
physical.udp");
+ /* yes, we pick up a random one : it will be updated on handshake */
+ detectedPeer=(Peer) nominalPeer.firstElement();
+
String name = fs.get("myName");
if(name == null) throw new FSParseException("No name");
if(!name.equals(myName)) changedAnything = true;
@@ -882,7 +940,8 @@
*/
private SimpleFieldSet exportFieldSet() {
SimpleFieldSet fs = new SimpleFieldSet();
- fs.put("physical.udp", peer.toString());
+ for(int i=0;i<nominalPeer.size();i++)
+ fs.put("physical.udp", nominalPeer.get(i).toString());
fs.put("identity", HexUtil.bytesToHex(identity));
fs.put("location", Double.toString(currentLocation.getValue()));
fs.put("testnet", Boolean.toString(testnetEnabled));
Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-01-31
01:03:51 UTC (rev 7965)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-01-31
01:47:58 UTC (rev 7966)
@@ -651,7 +651,7 @@
PeerNode[] pn = n.peers.myPeers;
for(int i=0;i<pn.length;i++)
{
- String nodeIpAndPort =
pn[i].getPeer().getAddress().getHostAddress()+":"+pn[i].getPeer().getPort();
+ String nodeIpAndPort =
pn[i].getDetectedPeer().getAddress().getHostAddress()+":"+pn[i].getDetectedPeer().getPort();
if(nodeIpAndPort.equals(ipAndPort))
{
n.peers.disconnect(pn[i]);
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-01-31 01:03:51 UTC (rev
7965)
+++ trunk/freenet/src/freenet/node/Version.java 2006-01-31 01:47:58 UTC (rev
7966)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 416;
+ private static final int buildNumber = 417;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 403;
Modified: trunk/freenet/src/freenet/support/SimpleFieldSet.java
===================================================================
--- trunk/freenet/src/freenet/support/SimpleFieldSet.java 2006-01-31
01:03:51 UTC (rev 7965)
+++ trunk/freenet/src/freenet/support/SimpleFieldSet.java 2006-01-31
01:47:58 UTC (rev 7966)
@@ -11,6 +11,8 @@
import java.util.Map;
import java.util.Set;
+import java.util.Vector;
+
import freenet.support.io.LineReader;
/**
@@ -53,6 +55,20 @@
}
/**
+ * Construct from a string[].
+ * @throws IOException if the string is too short or invalid.
+ */
+ public SimpleFieldSet(String[] content) throws IOException {
+ map = new HashMap();
+ String content2=new String();
+ for(int i=0;i<content.length;i++)
+ content2.concat(content[i]+";");
+ StringReader sr = new StringReader(content2);
+ BufferedReader br = new BufferedReader(sr);
+ read(br);
+ }
+
+ /**
* Read from disk
* Format:
* blah=blah
@@ -116,9 +132,36 @@
public String get(String key) {
return (String) map.get(key);
}
+
+ public String[] getAll(String key) {
+ int index = key.indexOf(';');
+ if(index == -1) return null;
+ Vector v=new Vector();
+ v.removeAllElements();
+ while(index>0){
+ // Mapping
+ String before = key.substring(0, index);
+ String after = key.substring(index+1);
+ v.addElement(before);
+ key=after;
+ index = key.indexOf(';');
+ }
+
+ return (String[]) v.toArray();
+ }
public void put(String key, String value) {
- map.put(key, value);
+ String test=null;
+ try{
+ if(map.get(key) != null)
+ test=new String((String) map.get(key));
+ }catch (Exception e){
+ }
+ if(test != null && test.equalsIgnoreCase(value)){
+ map.put(key, test+";"+value);
+ }else{
+ map.put(key, value);
+ }
}
/**