Author: toad
Date: 2007-06-29 17:30:56 +0000 (Fri, 29 Jun 2007)
New Revision: 13823

Added:
   trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java
   trunk/freenet/src/freenet/node/NodeCryptoConfig.java
   trunk/freenet/src/freenet/node/OpennetManager.java
   trunk/freenet/src/freenet/node/OpennetPeerNode.java
   trunk/freenet/src/freenet/node/OpennetPeerNodeStatus.java
Modified:
   trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
   trunk/freenet/src/freenet/node/DarknetPeerNode.java
   trunk/freenet/src/freenet/node/FNPPacketMangler.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodeARKInserter.java
   trunk/freenet/src/freenet/node/NodeCrypto.java
   trunk/freenet/src/freenet/node/PeerManager.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/node/TestnetHandler.java
   trunk/freenet/src/freenet/node/TestnetStatusUploader.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/node/fcp/NodeData.java
   trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java
Log:
Fix bugs, add support for opennet nodes (these are not very different from 
darknet nodes yet), second port, Opennet page on web interface, node.opennet 
config section etc - infrastructure for opennet (includes much refactoring)

Modified: trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java      
2007-06-29 16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java      
2007-06-29 17:30:56 UTC (rev 13823)
@@ -33,6 +33,65 @@

 public abstract class ConnectionsToadlet extends Toadlet {

+       protected class ComparatorByStatus implements Comparator {
+               
+               protected final String sortBy;
+               protected final boolean reversed;
+               
+               ComparatorByStatus(String sortBy, boolean reversed) {
+                       this.sortBy = sortBy;
+                       this.reversed = reversed;
+               }
+               
+               public int compare(Object first, Object second) {
+                       int result = 0;
+                       boolean isSet = true;
+                       PeerNodeStatus firstNode = (DarknetPeerNodeStatus) 
first;
+                       PeerNodeStatus secondNode = (DarknetPeerNodeStatus) 
second;
+                       
+                       if(sortBy != null){
+                               result = customCompare(firstNode, secondNode, 
sortBy);
+                               isSet = (result != 0);
+                               
+                       }else
+                               isSet=false;
+                       
+                       if(!isSet){
+                               int statusDifference = 
firstNode.getStatusValue() - secondNode.getStatusValue();
+                               if (statusDifference != 0) 
+                                       result = (statusDifference < 0 ? -1 : 
1);
+                               else
+                                       result = lastResortCompare(firstNode, 
secondNode);
+                       }
+
+                       if(result == 0){
+                               return 0;
+                       }else if(reversed){
+                               isReversed = true;
+                               return result > 0 ? -1 : 1;
+                       }else{
+                               isReversed = false;
+                               return result < 0 ? -1 : 1;
+                       }
+               }
+
+               protected int customCompare(PeerNodeStatus firstNode, 
PeerNodeStatus secondNode, String sortBy2) {
+                       if(sortBy.equals("address")){
+                               return 
firstNode.getPeerAddress().compareToIgnoreCase(secondNode.getPeerAddress());
+                       }else if(sortBy.equals("location")){
+                               return (firstNode.getLocation() - 
secondNode.getLocation()) < 0 ? -1 : 1; // Shouldn't be equal anyway
+                       }else if(sortBy.equals("version")){
+                               return 
Version.getArbitraryBuildNumber(firstNode.getVersion()) - 
Version.getArbitraryBuildNumber(secondNode.getVersion());
+                       }else
+                               return 0;
+               }
+
+               /** Default comparison, after taking into account status */
+               protected int lastResortCompare(PeerNodeStatus firstNode, 
PeerNodeStatus secondNode) {
+                       return (firstNode.getLocation() - 
secondNode.getLocation()) < 0 ? -1 : 1;
+               }
+       }
+
        protected final Node node;
        protected final NodeClientCore core;
        protected final NodeStats stats;
@@ -55,7 +114,7 @@
        public void handleGet(URI uri, final HTTPRequest request, 
ToadletContext ctx) throws ToadletContextClosedException, IOException, 
RedirectException {
                String path = uri.getPath();
                if(path.endsWith("myref.fref")) {
-                       SimpleFieldSet fs = node.exportPublicFieldSet();
+                       SimpleFieldSet fs = getNoderef();
                        StringWriter sw = new StringWriter();
                        fs.writeTo(sw);
                        MultiValueTable extraHeaders = new MultiValueTable();
@@ -66,7 +125,7 @@
                }

                if(path.endsWith("myref.txt")) {
-                       SimpleFieldSet fs = node.exportPublicFieldSet();
+                       SimpleFieldSet fs = getNoderef();
                        StringWriter sw = new StringWriter();
                        fs.writeTo(sw);
                        this.writeReply(ctx, 200, "text/plain", "OK", 
sw.toString());
@@ -82,51 +141,8 @@
                final boolean fProxyJavascriptEnabled = 
node.isFProxyJavascriptEnabled();

                /* gather connection statistics */
-               DarknetPeerNodeStatus[] peerNodeStatuses = 
peers.getDarknetPeerNodeStatuses();
-               Arrays.sort(peerNodeStatuses, new Comparator() {
-                       public int compare(Object first, Object second) {
-                               int result = 0;
-                               boolean isSet = true;
-                               DarknetPeerNodeStatus firstNode = 
(DarknetPeerNodeStatus) first;
-                               DarknetPeerNodeStatus secondNode = 
(DarknetPeerNodeStatus) second;
-                               
-                               if(request.isParameterSet("sortBy")){
-                                       final String sortBy = 
request.getParam("sortBy"); 
-
-                                       if(sortBy.equals("name")){
-                                               result = 
firstNode.getName().compareToIgnoreCase(secondNode.getName());
-                                       }else if(sortBy.equals("address")){
-                                               result = 
firstNode.getPeerAddress().compareToIgnoreCase(secondNode.getPeerAddress());
-                                       }else if(sortBy.equals("location")){
-                                               result = 
(firstNode.getLocation() - secondNode.getLocation()) < 0 ? -1 : 1; // Shouldn't 
be equal anyway
-                                       }else if(sortBy.equals("version")){
-                                               result = 
Version.getArbitraryBuildNumber(firstNode.getVersion()) - 
Version.getArbitraryBuildNumber(secondNode.getVersion());
-                                       }else if(sortBy.equals("privnote")){
-                                               result = 
firstNode.getPrivateDarknetCommentNote().compareToIgnoreCase(secondNode.getPrivateDarknetCommentNote());
-                                       }else
-                                               isSet=false;
-                               }else
-                                       isSet=false;
-                               
-                               if(!isSet){
-                                       int statusDifference = 
firstNode.getStatusValue() - secondNode.getStatusValue();
-                                       if (statusDifference != 0) 
-                                               result = (statusDifference < 0 
? -1 : 1);
-                                       else
-                                               result = 
firstNode.getName().compareToIgnoreCase(secondNode.getName());
-                               }
-
-                               if(result == 0){
-                                       return 0;
-                               }else if(request.isParameterSet("reversed")){
-                                       isReversed = true;
-                                       return result > 0 ? -1 : 1;
-                               }else{
-                                       isReversed = false;
-                                       return result < 0 ? -1 : 1;
-                               }
-                       }
-               });
+               PeerNodeStatus[] peerNodeStatuses = getPeerNodeStatuses();
+               Arrays.sort(peerNodeStatuses, 
comparator(request.getParam("sortBy", null), 
request.isParameterSet("reversed")));

                int numberOfConnected = 
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses, 
PeerManager.PEER_NODE_STATUS_CONNECTED);
                int numberOfRoutingBackedOff = 
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses, 
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF);
@@ -433,7 +449,7 @@
                L10n.addL10nSubstitution(warningSentence, 
"DarknetConnectionsToadlet.referenceCopyWarning",
                                new String[] { "bold", "/bold" },
                                new String[] { "<b>", "</b>" });
-               referenceInfobox.addChild("div", "class", 
"infobox-content").addChild("pre", "id", "reference", 
node.exportPublicFieldSet().toString() + '\n');
+               referenceInfobox.addChild("div", "class", 
"infobox-content").addChild("pre", "id", "reference", getNoderef().toString() + 
'\n');

                // our ports
                HTMLNode portInfobox = contentNode.addChild("div", "class", 
"infobox infobox-normal");
@@ -468,6 +484,14 @@
        }


+       protected Comparator comparator(String sortBy, boolean reversed) {
+               return new ComparatorByStatus(sortBy, reversed);
+       }
+
+       abstract protected PeerNodeStatus[] getPeerNodeStatuses();
+
+       abstract protected SimpleFieldSet getNoderef();
+
        private void drawRow(HTMLNode peerTable, PeerNodeStatus peerNodeStatus, 
boolean advancedModeEnabled, boolean fProxyJavascriptEnabled, long now, String 
path) {
                HTMLNode peerRow = peerTable.addChild("tr");


Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2007-06-29 16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2007-06-29 17:30:56 UTC (rev 13823)
@@ -7,6 +7,7 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashMap;

 import freenet.client.HighLevelSimpleClient;
@@ -40,6 +41,32 @@
                return L10n.getString("DarknetConnectionsToadlet."+string);
        }

+       protected class DarknetComparator extends ComparatorByStatus {
+
+               DarknetComparator(String sortBy, boolean reversed) {
+                       super(sortBy, reversed);
+               }
+       
+               protected int customCompare(PeerNodeStatus firstNode, 
PeerNodeStatus secondNode, String sortBy) {
+                       if(sortBy.equals("name")) {
+                               return 
((DarknetPeerNodeStatus)firstNode).getName().compareToIgnoreCase(((DarknetPeerNodeStatus)secondNode).getName());
+                       }else if(sortBy.equals("privnote")){
+                               return 
((DarknetPeerNodeStatus)firstNode).getPrivateDarknetCommentNote().compareToIgnoreCase(((DarknetPeerNodeStatus)secondNode).getPrivateDarknetCommentNote());
+                       } else
+                               return super.customCompare(firstNode, 
secondNode, sortBy);
+               }
+               
+               /** Default comparison, after taking into account status */
+               protected int lastResortCompare(PeerNodeStatus firstNode, 
PeerNodeStatus secondNode) {
+                       return 
((DarknetPeerNodeStatus)firstNode).getName().compareToIgnoreCase(((DarknetPeerNodeStatus)secondNode).getName());
+               }
+
+       }
+       
+       protected Comparator comparator(String sortBy, boolean reversed) {
+               return new DarknetComparator(sortBy, reversed);
+       }
+               
        public void handlePost(URI uri, final HTTPRequest request, 
ToadletContext ctx) throws ToadletContextClosedException, IOException, 
RedirectException {
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);

@@ -409,5 +436,13 @@
                }
        }

+       protected SimpleFieldSet getNoderef() {
+               return node.exportDarknetPublicFieldSet();
+       }

+       protected PeerNodeStatus[] getPeerNodeStatuses() {
+               return node.peers.getDarknetPeerNodeStatuses();
+       }
+
+
 }

Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2007-06-29 
16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2007-06-29 
17:30:56 UTC (rev 13823)
@@ -599,6 +599,9 @@
 //                     server.register(friendsToadlet, "/darknet/", true, 
l10n("friendsTitle"), l10n("friends"), true);
                        server.register(friendsToadlet, "/friends/", true, 
l10n("friendsTitle"), l10n("friends"), true);

+                       OpennetConnectionsToadlet opennetToadlet = new 
OpennetConnectionsToadlet(node, core, client);
+                       server.register(opennetToadlet, "/opennet/", true, 
l10n("opennetTitle"), l10n("opennet"), true);
+                       
                        N2NTMToadlet n2ntmToadlet = new N2NTMToadlet(node, 
core, client);
                        server.register(n2ntmToadlet, "/send_n2ntm/", true, 
true);


Added: trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java       
                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java       
2007-06-29 17:30:56 UTC (rev 13823)
@@ -0,0 +1,42 @@
+package freenet.clients.http;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.node.Node;
+import freenet.node.NodeClientCore;
+import freenet.node.PeerNodeStatus;
+import freenet.support.HTMLNode;
+import freenet.support.SimpleFieldSet;
+
+public class OpennetConnectionsToadlet extends ConnectionsToadlet {
+
+       protected OpennetConnectionsToadlet(Node n, NodeClientCore core, 
HighLevelSimpleClient client) {
+               super(n, core, client);
+       }
+
+       protected void drawNameColumn(HTMLNode peerRow,
+                       PeerNodeStatus peerNodeStatus) {
+               // Do nothing - no names on opennet
+       }
+
+       protected void drawPrivateNoteColumn(HTMLNode peerRow,
+                       PeerNodeStatus peerNodeStatus, boolean 
fProxyJavascriptEnabled) {
+               // Do nothing - no private notes either (no such thing as 
negative trust in cyberspace)
+       }
+
+       protected boolean hasNameColumn() {
+               return false;
+       }
+
+       protected boolean hasPrivateNoteColumn() {
+               return false;
+       }
+
+       protected SimpleFieldSet getNoderef() {
+               return node.exportOpennetPublicFieldSet();
+       }
+
+       protected PeerNodeStatus[] getPeerNodeStatuses() {
+               return node.peers.getOpennetPeerNodeStatuses();
+       }
+
+}

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2007-06-29 
16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2007-06-29 
17:30:56 UTC (rev 13823)
@@ -227,6 +227,8 @@
 FProxyToadlet.openPossRSSAsPlainText=${link}Click here${/link} to open the 
file as plain text (this ${bold}may be dangerous${/bold} if you are running IE7 
or FF2).
 FProxyToadlet.openRSSAsRSS=${link}Click here${/link} to open the file as RSS 
(this ${bold}is dangerous${/bold} if the site author is malicious as Freenet 
does not know how to filter RSS yet).
 FProxyToadlet.openRSSForce=${link}Click here${/link} to open the file as 
${mime} (this ${bold}may be dangerous${/bold} on IE7 or FF2).
+FProxyToadlet.opennet=manage opennet peers
+FProxyToadlet.opennetTitle=Opennet
 FProxyToadlet.options=Your options are:
 FProxyToadlet.pathNotFound=The specified path does not exist.
 FProxyToadlet.pathNotFoundTitle=Path Not Found
@@ -513,6 +515,8 @@
 Node.nodeDirLong=Name of directory to put node-related files e.g. peers list in
 Node.nodeName=Nickname for this Freenet node
 Node.nodeNameLong=Node nickname. This will be visible to your friends only.
+Node.opennetEnabled=Enable Opennet support?
+Node.opennetEnabledLong=Enable Opennet? If opennet is enabled, the node will 
automatically exchange node references with other nodes. But this means that 
the fact that you are running a node is no longer private, and many attacks are 
much easier. If you know enough people running Freenet, you should stick to 
darknet connections to them.
 Node.outBWLimit=Output bandwidth limit (bytes per second)
 Node.outBWLimitLong=Hard output bandwidth limit (bytes/sec); the node should 
almost never exceed this
 Node.port=FNP port number (UDP)

Modified: trunk/freenet/src/freenet/node/DarknetPeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/DarknetPeerNode.java 2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/DarknetPeerNode.java 2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -188,7 +188,7 @@
     }

     public synchronized SimpleFieldSet exportFieldSet() {
-       SimpleFieldSet fs = super.exportMetadataFieldSet();
+       SimpleFieldSet fs = super.exportFieldSet();
        fs.putSingle("myName", getName());
        return fs;
     }

Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java        2007-06-29 
16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java        2007-06-29 
17:30:56 UTC (rev 13823)
@@ -333,7 +333,7 @@
         PCFBMode pcfb = PCFBMode.create(cipher);
         byte[] iv = new byte[pcfb.lengthIV()];

-        byte[] myRef = node.myCompressedSetupRef();
+        byte[] myRef = crypto.myCompressedSetupRef();
         byte[] data = new byte[myRef.length + 8];
         System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 0, 8);
         System.arraycopy(myRef, 0, data, 8, myRef.length);

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2007-06-29 16:11:36 UTC (rev 
13822)
+++ trunk/freenet/src/freenet/node/Node.java    2007-06-29 17:30:56 UTC (rev 
13823)
@@ -8,7 +8,6 @@

 import java.io.BufferedReader;
 import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -26,7 +25,6 @@
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.Random;
-import java.util.zip.DeflaterOutputStream;

 import org.spaceroots.mantissa.random.MersenneTwister;
 import org.tanukisoftware.wrapper.WrapperManager;
@@ -46,7 +44,6 @@
 import freenet.config.PersistentConfig;
 import freenet.config.SubConfig;
 import freenet.crypt.DSAPublicKey;
-import freenet.crypt.DSASignature;
 import freenet.crypt.RandomSource;
 import freenet.crypt.SHA256;
 import freenet.io.comm.DMT;
@@ -297,12 +294,6 @@
        /** Semi-unique ID for swap requests. Used to identify us so that the
         * topology can be reconstructed. */
        public long swapIdentifier;
-       /** The signature of the above fieldset */
-       private DSASignature myReferenceSignature = null;
-       /** A synchronization object used while signing the reference fiedlset 
*/
-       private volatile Object referenceSync = new Object();
-       /** An ordered version of the FieldSet, without the signature */
-       private String mySignedReference = null;
        private String myName;
        final LocationManager lm;
        /** My peers */
@@ -324,7 +315,8 @@

        // Opennet stuff

-       private NodeCrypto opennetCrypto;
+       private final NodeCryptoConfig opennetCryptoConfig;
+       private OpennetManager opennet;

        // General stuff

@@ -459,7 +451,7 @@
        }

        private void writeNodeFile(File orig, File backup) {
-               SimpleFieldSet fs = exportPrivateFieldSet();
+               SimpleFieldSet fs = darknetCrypto.exportPrivateFieldSet();

                if(orig.exists()) backup.delete();

@@ -608,7 +600,9 @@

                // Determine the port number

-               darknetCrypto = new NodeCrypto(nodeConfig, sortOrder++, this);
+               NodeCryptoConfig darknetConfig = new 
NodeCryptoConfig(nodeConfig, sortOrder++);
+               sortOrder += NodeCryptoConfig.OPTION_COUNT;
+               darknetCrypto = new NodeCrypto(sortOrder++, this, false, 
darknetConfig);

                // Must be created after darknetCrypto
                dnsr = new DNSRequester(this);
@@ -767,10 +761,53 @@
                usm.setDispatcher(dispatcher=new NodeDispatcher(this));

                // Then read the peers
-               peers = new PeerManager(this, darknetCrypto, new File(nodeDir, 
"peers-"+getDarknetPortNumber()).getPath(), darknetCrypto.packetMangler);
+               peers = new PeerManager(this);
+               peers.tryReadPeers(new File(nodeDir, 
"peers-"+getDarknetPortNumber()).getPath(), darknetCrypto, false);
                peers.writePeers();
                peers.updatePMUserAlert();

+               // Opennet
+               
+               final SubConfig opennetConfig = new SubConfig("node.opennet", 
config);
+               
+               // Can be enabled on the fly
+               opennetConfig.register("enabled", false, 0, false, true, 
"Node.opennetEnabled", "Node.opennetEnabledLong", new BooleanCallback() {
+                       public boolean get() {
+                               synchronized(Node.this) {
+                                       return opennet != null;
+                               }
+                       }
+                       public void set(boolean val) throws 
InvalidConfigValueException {
+                               synchronized(Node.this) {
+                                       if(val == (opennet != null)) return;
+                                       if(val) {
+                                               try {
+                                                       opennet = new 
OpennetManager(Node.this, opennetCryptoConfig);
+                                               } catch (NodeInitException e) {
+                                                       throw new 
InvalidConfigValueException(e.getMessage());
+                                               }
+                                       } else {
+                                               opennet = null;
+                                       }
+                               }
+                               if(val) opennet.start();
+                               else opennet.stop();
+                       }
+               });
+               
+               boolean opennetEnabled = opennetConfig.getBoolean("enabled");
+               
+               opennetCryptoConfig = new NodeCryptoConfig(opennetConfig, 1 /* 
0 = enabled */);
+               
+               if(opennetEnabled) {
+                       opennet = new OpennetManager(this, opennetCryptoConfig);
+                       // Will be started later
+               } else {
+                       opennet = null;
+               }
+               
+               opennetConfig.finishedInitialization();
+               
                // Extra Peer Data Directory
                nodeConfig.register("extraPeerDataDir", new File(nodeDir, 
"extra-peer-data-"+getDarknetPortNumber()).toString(), sortOrder++, true, 
false, "Node.extraPeerDir", "Node.extraPeerDirLong",
                                new StringCallback() {
@@ -1216,6 +1253,8 @@

                usm.start(ps);
                darknetCrypto.start(disableHangCheckers);
+               if(opennet != null)
+                       opennet.start();

                if(isUsingWrapper()) {
                        Logger.normal(this, "Using wrapper correctly: 
"+nodeStarter);
@@ -1456,61 +1495,7 @@
                return L10n.getString("Node."+key, pattern, value);
        }

-       public SimpleFieldSet exportPrivateFieldSet() {
-               SimpleFieldSet fs = exportPublicFieldSet(false);
-               darknetCrypto.addPrivateFields(fs);
-               return fs;
-       }
-       
        /**
-        * Export my node reference so that another node can connect to me.
-        * Public version, includes everything apart from private keys.
-        * @see exportPublicFieldSet(boolean forSetup).
-        */
-       public SimpleFieldSet exportPublicFieldSet() {
-               return exportPublicFieldSet(false);
-       }
-       
-       /**
-        * Export my reference so that another node can connect to me.
-        * @param forSetup If true, strip out everything that isn't needed for 
the references
-        * exchanged immediately after connection setup. I.e. strip out 
everything that is invariant,
-        * or that can safely be exchanged later.
-        */
-       SimpleFieldSet exportPublicFieldSet(boolean forSetup) {
-               SimpleFieldSet fs = 
darknetCrypto.exportPublicFieldSet(forSetup);
-               // IP addresses
-               Peer[] ips = ipDetector.getPrimaryIPAddress();
-               if(ips != null) {
-                       for(int i=0;i<ips.length;i++)
-                               fs.putAppend("physical.udp", 
ips[i].toString()); // Keep; important that node know all our IPs
-               }
-               // Negotiation types
-               fs.put("location", lm.getLocation().getValue()); // FIXME maybe 
!forSetup; see #943
-               fs.putSingle("version", Version.getVersionString()); // Keep, 
vital that peer know our version. For example, some types may be sent in 
different formats to different node versions (e.g. Peer).
-               fs.put("testnet", testnetEnabled); // Vital that peer know this!
-               fs.putSingle("lastGoodVersion", 
Version.getLastGoodVersionString()); // Also vital
-               if(testnetEnabled)
-                       fs.put("testnetPort", testnetHandler.getPort()); // 
Useful, saves a lot of complexity
-               fs.putSingle("myName", myName); // FIXME see #942
-               
-               synchronized (referenceSync) {
-                       if(myReferenceSignature == null || mySignedReference == 
null || !mySignedReference.equals(fs.toOrderedString())){
-                               mySignedReference = fs.toOrderedString();
-                               try {
-                                       myReferenceSignature = 
darknetCrypto.signRef(mySignedReference);
-                               } catch (NodeInitException e) {
-                                       exit(e.exitCode);
-                               }
-                       }
-                       fs.putSingle("sig", 
myReferenceSignature.toLongString());
-               }
-               
-               if(logMINOR) Logger.minor(this, "My reference: 
"+fs.toOrderedString());
-               return fs;
-       }
-
-       /**
         * Export volatile data about the node as a SimpleFieldSet
         */
        public SimpleFieldSet exportVolatileFieldSet() {
@@ -2099,34 +2084,6 @@
                return sb.toString();
        }

-       /**
-        * The part of our node reference which is exchanged in the connection 
setup, compressed.
-        * @see exportSetupFieldSet()
-        */
-       public byte[] myCompressedSetupRef() {
-               SimpleFieldSet fs = exportPublicFieldSet(true);
-               ByteArrayOutputStream baos = new ByteArrayOutputStream();
-               DeflaterOutputStream gis;
-               gis = new DeflaterOutputStream(baos);
-               OutputStreamWriter osw = new OutputStreamWriter(gis);
-               BufferedWriter bw = new BufferedWriter(osw);
-               try {
-                       fs.writeTo(bw);
-               } catch (IOException e) {
-                       throw new Error(e);
-               }
-               try {
-                       bw.close();
-               } catch (IOException e1) {
-                       throw new Error(e1);
-               }
-               byte[] buf = baos.toByteArray();
-               byte[] obuf = new byte[buf.length + 1];
-               obuf[0] = 1;
-               System.arraycopy(buf, 0, obuf, 1, buf.length);
-               return obuf;
-       }
-
        final LRUQueue recentlyCompletedIDs;

        static final int MAX_RECENTLY_COMPLETED_IDS = 10*1000;
@@ -2560,7 +2517,7 @@
         * Connect this node to another node (for purposes of testing) 
         */
        public void connect(Node node) throws FSParseException, 
PeerParseException, ReferenceSignatureVerificationException {
-               peers.connect(node.exportPublicFieldSet(), 
darknetCrypto.packetMangler);
+               peers.connect(node.darknetCrypto.exportPublicFieldSet(), 
darknetCrypto.packetMangler);
        }

        public short maxHTL() {
@@ -2612,4 +2569,20 @@
        public int estimateFullHeadersLengthOneMessage() {
                return 
darknetCrypto.packetMangler.fullHeadersLengthOneMessage();
        }
+
+       public synchronized boolean isOpennetEnabled() {
+               return opennet != null;
+       }
+
+       public SimpleFieldSet exportDarknetPublicFieldSet() {
+               return darknetCrypto.exportPublicFieldSet();
+       }
+
+       public SimpleFieldSet exportOpennetPublicFieldSet() {
+               return opennet.crypto.exportPublicFieldSet();
+       }
+
+       public SimpleFieldSet exportDarknetPrivateFieldSet() {
+               return darknetCrypto.exportPrivateFieldSet();
+       }
 }

Modified: trunk/freenet/src/freenet/node/NodeARKInserter.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeARKInserter.java 2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/NodeARKInserter.java 2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -109,7 +109,7 @@

                if(logMINOR) Logger.minor(this, "starting inserter");

-               SimpleFieldSet fs = this.node.exportPublicFieldSet(true); // 
More or less
+               SimpleFieldSet fs = crypto.exportPublicFieldSet(true); // More 
or less

                // Remove some unnecessary fields that only cause collisions.


Modified: trunk/freenet/src/freenet/node/NodeCrypto.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCrypto.java      2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/NodeCrypto.java      2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -1,16 +1,20 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.security.MessageDigest;
+import java.util.zip.DeflaterOutputStream;

 import net.i2p.util.NativeBigInteger;
-
-import freenet.config.InvalidConfigValueException;
-import freenet.config.SubConfig;
 import freenet.crypt.DSA;
 import freenet.crypt.DSAGroup;
 import freenet.crypt.DSAPrivateKey;
@@ -19,6 +23,7 @@
 import freenet.crypt.Global;
 import freenet.crypt.RandomSource;
 import freenet.crypt.SHA256;
+import freenet.io.comm.Peer;
 import freenet.io.comm.UdpSocketHandler;
 import freenet.keys.FreenetURI;
 import freenet.keys.InsertableClientSSK;
@@ -27,8 +32,6 @@
 import freenet.support.IllegalBase64Exception;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
-import freenet.support.api.IntCallback;
-import freenet.support.api.StringCallback;

 /**
  * Cryptographic and transport level node identity. 
@@ -36,11 +39,13 @@
  */
 class NodeCrypto {

+       final Node node;
+       final boolean isOpennet;
        final RandomSource random;
        /** The object which handles our specific UDP port, pulls messages from 
it, feeds them to the packet mangler for decryption etc */
        UdpSocketHandler socket;
        public FNPPacketMangler packetMangler;
-       final String bindto;
+       final InetAddress bindto;
        // FIXME: abstract out address stuff? Possibly to something like 
NodeReference?
        final int portNumber;
        byte[] myIdentity; // FIXME: simple identity block; should be unique
@@ -60,41 +65,32 @@
        long myARKNumber;
        static boolean logMINOR;

+       // Noderef related
+       /** The signature of the above fieldset */
+       private DSASignature myReferenceSignature = null;
+       /** A synchronization object used while signing the reference fiedlset 
*/
+       private volatile Object referenceSync = new Object();
+       /** An ordered version of the FieldSet, without the signature */
+       private String mySignedReference = null;
+       
        /**
         * Get port number from a config, create socket and packet mangler
         * @throws NodeInitException 
         */
-       public NodeCrypto(SubConfig nodeConfig, int sortOrder, Node node) 
throws NodeInitException {
-               
+       public NodeCrypto(int sortOrder, Node node, boolean isOpennet, 
NodeCryptoConfig config) throws NodeInitException {
+
+               this.node = node;
                random = node.random;
+               this.isOpennet = isOpennet;
                logMINOR = Logger.shouldLog(Logger.MINOR, this);

-               nodeConfig.register("listenPort", -1 /* means random */, 
sortOrder++, true, true, "Node.port", "Node.portLong", new IntCallback() {
-                       public int get() {
-                               return portNumber;
-                       }
-                       public void set(int val) throws 
InvalidConfigValueException {
-                               // FIXME implement on the fly listenPort 
changing
-                               // Note that this sort of thing should be the 
exception rather than the rule!!!!
-                               String msg = "Switching listenPort on the fly 
not yet supported!";
-                               Logger.error(this, msg);
-                               throw new InvalidConfigValueException(msg);
-                       }
-               });
+               config.starting(this);

-               int port=-1;
-               try{
-                       port=nodeConfig.getInt("listenPort");
-               }catch (Exception e){
-                       Logger.error(this, "Caught "+e, e);
-                       System.err.println(e);
-                       e.printStackTrace();
-                       port=-1;
-               }
+               try {

-               nodeConfig.register("bindTo", "0.0.0.0", sortOrder++, true, 
true, "Node.bindTo", "Node.bindToLong", new NodeBindtoCallback());
+               int port = config.getPort();

-               this.bindto = nodeConfig.getString("bindTo");
+               bindto = config.getBindTo();

                UdpSocketHandler u = null;

@@ -105,7 +101,7 @@
                        for(int i=0;i<200000;i++) {
                                int portNo = 1024 + random.nextInt(65535-1024);
                                try {
-                                       u = new UdpSocketHandler(portNo, 
InetAddress.getByName(bindto), node);
+                                       u = new UdpSocketHandler(portNo, 
bindto, node);
                                        port = u.getPortNumber();
                                        break;
                                } catch (Exception e) {
@@ -119,7 +115,7 @@
                                throw new 
NodeInitException(NodeInitException.EXIT_NO_AVAILABLE_UDP_PORTS, "Could not 
find an available UDP port number for FNP (none specified)");
                } else {
                        try {
-                               u = new UdpSocketHandler(port, 
InetAddress.getByName(bindto), node);
+                               u = new UdpSocketHandler(port, bindto, node);
                        } catch (Exception e) {
                                throw new 
NodeInitException(NodeInitException.EXIT_IMPOSSIBLE_USM_PORT, "Could not bind 
to port: "+port+" (node already running?)");
                        }
@@ -129,39 +125,25 @@
                Logger.normal(this, "FNP port created on "+bindto+ ':' +port);
                System.out.println("FNP port created on "+bindto+ ':' +port);
                portNumber = port;
+               config.setPort(port);

-               nodeConfig.register("testingDropPacketsEvery", 0, sortOrder++, 
true, false, "Node.dropPacketEvery", "Node.dropPacketEveryLong",
-                               new IntCallback() {
-
-                                       public int get() {
-                                               return 
((UdpSocketHandler)socket).getDropProbability();
-                                       }
-
-                                       public void set(int val) throws 
InvalidConfigValueException {
-                                               
((UdpSocketHandler)socket).setDropProbability(val);
-                                       }
-                       
-               });
+               
((UdpSocketHandler)socket).setDropProbability(config.getDropProbability());

-               int dropProb = nodeConfig.getInt("testingDropPacketsEvery");
-               ((UdpSocketHandler)socket).setDropProbability(dropProb);
-               
                socket.setLowLevelFilter(packetMangler = new 
FNPPacketMangler(node, this, socket));
+               } catch (NodeInitException e) {
+                       config.stopping(this);
+                       throw e;
+               } catch (RuntimeException e) {
+                       config.stopping(this);
+                       throw e;
+               } catch (Error e) {
+                       config.stopping(this);
+                       throw e;
+               } finally {
+                       config.maybeStarted(this);
+               }
        }

-       class NodeBindtoCallback implements StringCallback {
-               
-               public String get() {
-                       return bindto;
-               }
-               
-               public void set(String val) throws InvalidConfigValueException {
-                       if(val.equals(get())) return;
-                       // FIXME why not? Can't we use 
freenet.io.NetworkInterface like everywhere else, just adapt it for UDP?
-                       throw new InvalidConfigValueException("Cannot be 
updated on the fly");
-               }
-       }
-
        /**
         * Read the cryptographic keys etc from a SimpleFieldSet
         * @param fs
@@ -246,8 +228,64 @@
        public void start(boolean disableHangchecker) {
                socket.start(disableHangchecker);
        }
+       
+       public SimpleFieldSet exportPrivateFieldSet() {
+               SimpleFieldSet fs = exportPublicFieldSet(false);
+               addPrivateFields(fs);
+               return fs;
+       }
+       
+       /**
+        * Export my node reference so that another node can connect to me.
+        * Public version, includes everything apart from private keys.
+        * @see exportPublicFieldSet(boolean forSetup).
+        */
+       public SimpleFieldSet exportPublicFieldSet() {
+               return exportPublicFieldSet(false);
+       }
+       
+       /**
+        * Export my reference so that another node can connect to me.
+        * @param forSetup If true, strip out everything that isn't needed for 
the references
+        * exchanged immediately after connection setup. I.e. strip out 
everything that is invariant,
+        * or that can safely be exchanged later.
+        */
+       SimpleFieldSet exportPublicFieldSet(boolean forSetup) {
+               SimpleFieldSet fs = exportPublicCryptoFieldSet(forSetup);
+               // IP addresses
+               Peer[] ips = node.ipDetector.getPrimaryIPAddress();
+               if(ips != null) {
+                       for(int i=0;i<ips.length;i++)
+                               fs.putAppend("physical.udp", 
ips[i].toString()); // Keep; important that node know all our IPs
+               }
+               // Negotiation types
+               fs.put("location", node.lm.getLocation().getValue()); // FIXME 
maybe !forSetup; see #943
+               fs.putSingle("version", Version.getVersionString()); // Keep, 
vital that peer know our version. For example, some types may be sent in 
different formats to different node versions (e.g. Peer).
+               fs.put("testnet", node.testnetEnabled); // Vital that peer know 
this!
+               fs.putSingle("lastGoodVersion", 
Version.getLastGoodVersionString()); // Also vital
+               if(node.testnetEnabled)
+                       fs.put("testnetPort", node.testnetHandler.getPort()); 
// Useful, saves a lot of complexity
+               if(!isOpennet)
+                       fs.putSingle("myName", node.getMyName()); // FIXME see 
#942
+               
+               synchronized (referenceSync) {
+                       if(myReferenceSignature == null || mySignedReference == 
null || !mySignedReference.equals(fs.toOrderedString())){
+                               mySignedReference = fs.toOrderedString();
+                               try {
+                                       myReferenceSignature = 
signRef(mySignedReference);
+                               } catch (NodeInitException e) {
+                                       node.exit(e.exitCode);
+                               }
+                       }
+                       fs.putSingle("sig", 
myReferenceSignature.toLongString());
+               }
+               fs.put("opennet", isOpennet);
+               
+               if(logMINOR) Logger.minor(this, "My reference: 
"+fs.toOrderedString());
+               return fs;
+       }

-       SimpleFieldSet exportPublicFieldSet(boolean forSetup) {
+       SimpleFieldSet exportPublicCryptoFieldSet(boolean forSetup) {
                SimpleFieldSet fs = new SimpleFieldSet(true);
                int[] negTypes = packetMangler.supportedNegTypes();
                fs.put("auth.negTypes", negTypes);
@@ -283,15 +321,39 @@
                }
        }

+       /**
+        * The part of our node reference which is exchanged in the connection 
setup, compressed.
+        * @see exportSetupFieldSet()
+        */
+       public byte[] myCompressedSetupRef() {
+               SimpleFieldSet fs = exportPublicFieldSet(true);
+               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+               DeflaterOutputStream gis;
+               gis = new DeflaterOutputStream(baos);
+               OutputStreamWriter osw = new OutputStreamWriter(gis);
+               BufferedWriter bw = new BufferedWriter(osw);
+               try {
+                       fs.writeTo(bw);
+               } catch (IOException e) {
+                       throw new Error(e);
+               }
+               try {
+                       bw.close();
+               } catch (IOException e1) {
+                       throw new Error(e1);
+               }
+               byte[] buf = baos.toByteArray();
+               byte[] obuf = new byte[buf.length + 1];
+               obuf[0] = 1;
+               System.arraycopy(buf, 0, obuf, 1, buf.length);
+               return obuf;
+       }
+
        void addPrivateFields(SimpleFieldSet fs) {
                fs.put("dsaPrivKey", privKey.asFieldSet());
                fs.putSingle("ark.privURI", 
myARK.getInsertURI().toString(false, false));
        }

-       public String getBindTo(){
-               return this.bindto;
-       }
-       
        public int getIdentityHash(){
                return Fields.hashCode(identityHash);
        }
@@ -300,5 +362,12 @@
        DSASignature sign(byte[] hash) {
                return DSA.sign(cryptoGroup, privKey, new NativeBigInteger(1, 
hash), random);
        }
+
+       public void onSetDropProbability(int val) {
+               synchronized(this) {
+                       if(socket == null) return;
+               }
+               socket.setDropProbability(val);
+       }

 }

Added: trunk/freenet/src/freenet/node/NodeCryptoConfig.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCryptoConfig.java                        
        (rev 0)
+++ trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2007-06-29 
17:30:56 UTC (rev 13823)
@@ -0,0 +1,162 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
+import freenet.io.comm.FreenetInetAddress;
+import freenet.support.Logger;
+import freenet.support.api.IntCallback;
+import freenet.support.api.StringCallback;
+
+/**
+ * Tracks config parameters related to a NodeCrypto. The NodeCrypto may or may 
not exist. If it exists,
+ * parameter changes are passed on to it, if it doesn't, they can be changed 
trivially.
+ * 
+ * Allows users to set the opennet port number while opennet is disabled, 
enable opennet on the fly etc.
+ * @author toad
+ */
+public class NodeCryptoConfig {
+
+       /** Port number. -1 = choose a random available port number at 
activation time. */
+       private int portNumber;
+       
+       /** Bind address. 0.0.0.0 = all addresses. */
+       private InetAddress bindTo;
+       
+       /** If nonzero, 1/dropProbability = probability of UdpSocketHandler 
dropping a packet (for debugging
+        * purposes; not static as we may need to simulate some nodes with more 
loss than others). */
+       private int dropProbability;
+       
+       /** The NodeCrypto, if there is one */
+       private NodeCrypto crypto;
+       
+       /** Whether the NodeCrypto has finished starting */
+       private boolean started;
+       
+       NodeCryptoConfig(SubConfig config, int sortOrder) throws 
NodeInitException {
+               
+               config.register("listenPort", -1 /* means random */, 
sortOrder++, true, true, "Node.port", "Node.portLong",     new IntCallback() {
+                       public int get() {
+                               synchronized(NodeCryptoConfig.class) {
+                                       if(crypto != null)
+                                               portNumber = crypto.portNumber;
+                                       return portNumber;
+                               }
+                       }
+                       public void set(int val) throws 
InvalidConfigValueException {
+                               
+                               if(portNumber < -1 || portNumber == 0 || 
portNumber > 65535) {
+                                       throw new 
InvalidConfigValueException("Invalid port number");
+                               }
+                               
+                               
+                               synchronized(NodeCryptoConfig.class) {
+                                       if(portNumber == val) return;
+                                       // FIXME implement on the fly 
listenPort changing
+                                       // Note that this sort of thing should 
be the exception rather than the rule!!!!
+                                       if(crypto != null)
+                                               throw new 
InvalidConfigValueException("Switching listenPort on the fly not yet 
supported");
+                                       portNumber = val;
+                               }
+                       }
+               });
+               
+               try{
+                       portNumber = config.getInt("listenPort");
+               }catch (Exception e){
+                       // FIXME is this really necessary?
+                       Logger.error(this, "Caught "+e, e);
+                       System.err.println(e);
+                       e.printStackTrace();
+                       portNumber = -1;
+               }
+               
+               config.register("bindTo", "0.0.0.0", sortOrder++, true, true, 
"Node.bindTo", "Node.bindToLong", new NodeBindtoCallback());
+               
+               try {
+                       bindTo = 
InetAddress.getByName(config.getString("bindTo"));
+               } catch (UnknownHostException e) {
+                       throw new 
NodeInitException(NodeInitException.EXIT_COULD_NOT_BIND_USM, "Invalid bindTo: 
"+config.getString("bindTo"));
+               }
+               
+               config.register("testingDropPacketsEvery", 0, sortOrder++, 
true, false, "Node.dropPacketEvery", "Node.dropPacketEveryLong",
+                               new IntCallback() {
+
+                                       public int get() {
+                                               
synchronized(NodeCryptoConfig.this) {
+                                                       return dropProbability;
+                                               }
+                                       }
+
+                                       public void set(int val) throws 
InvalidConfigValueException {
+                                               if(val < 0) throw new 
InvalidConfigValueException("testingDropPacketsEvery must not be negative");
+                                               
synchronized(NodeCryptoConfig.this) {
+                                                       if(val == 
dropProbability) return;
+                                                       dropProbability = val;
+                                                       if(crypto == null) 
return;
+                                               }
+                                               
crypto.onSetDropProbability(val);
+                                       }
+                       
+               });
+               
+       }
+
+       /** The number of config options i.e. the amount to increment sortOrder 
by */
+       public static final int OPTION_COUNT = 3;
+       
+       synchronized void starting(NodeCrypto crypto2) {
+               if(crypto != null) throw new IllegalStateException("Replacing 
existing NodeCrypto "+crypto+" with "+crypto2);
+               crypto = crypto2;
+               started = false;
+       }
+       
+       synchronized void started(NodeCrypto crypto2) {
+               if(crypto != null) throw new IllegalStateException("Replacing 
existing NodeCrypto "+crypto+" with "+crypto2);
+               started = true;
+       }
+       
+       synchronized void maybeStarted(NodeCrypto crypto2) {
+               if(crypto != null)
+                       started = true;
+       }
+       
+       synchronized void stopping(NodeCrypto crypto2) {
+               crypto = null;
+       }
+       
+       public int getPort() {
+               return portNumber;
+       }
+       
+       class NodeBindtoCallback implements StringCallback {
+               
+               public String get() {
+                       return FreenetInetAddress.getHostName(bindTo);
+               }
+               
+               public void set(String val) throws InvalidConfigValueException {
+                       if(val.equals(get())) return;
+                       // FIXME why not? Can't we use 
freenet.io.NetworkInterface like everywhere else, just adapt it for UDP?
+                       throw new InvalidConfigValueException("Cannot be 
updated on the fly");
+               }
+       }
+
+       public InetAddress getBindTo() {
+               return bindTo;
+       }
+
+       public synchronized void setPort(int port) {
+               portNumber = port;
+       }
+
+       public synchronized int getDropProbability() {
+               return dropProbability;
+       }
+
+}

Added: trunk/freenet/src/freenet/node/OpennetManager.java
===================================================================
--- trunk/freenet/src/freenet/node/OpennetManager.java                          
(rev 0)
+++ trunk/freenet/src/freenet/node/OpennetManager.java  2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -0,0 +1,85 @@
+package freenet.node;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import freenet.io.comm.Peer;
+import freenet.io.comm.PeerParseException;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * Central location for all things opennet.
+ * In particular:
+ * - Opennet crypto
+ * - LRU connections
+ * @author toad
+ */
+public class OpennetManager {
+       
+       final Node node;
+       final NodeCrypto crypto;
+
+       public OpennetManager(Node node, NodeCryptoConfig opennetConfig) throws 
NodeInitException {
+               this.node = node;
+               crypto =
+                       new NodeCrypto(1 /* 0 is enabled */, node, true, 
opennetConfig);
+
+               // Keep opennet crypto details in a separate file
+               try {
+                       readFile(new File(node.nodeDir, 
"opennet-"+crypto.portNumber).getPath());
+               } catch (IOException e) {
+                       try {
+                               readFile(new 
File("node-"+crypto.portNumber+".bak").getPath());
+                       } catch (IOException e1) {
+                               crypto.initCrypto();
+                       }
+               }
+               node.peers.tryReadPeers(new File(node.nodeDir, 
"openpeers-"+crypto.portNumber).toString(), crypto, true);
+       }
+
+       private void readFile(String filename) throws IOException {
+               // REDFLAG: Any way to share this code with Node and NodePeer?
+               FileInputStream fis = new FileInputStream(filename);
+               InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+               BufferedReader br = new BufferedReader(isr);
+               SimpleFieldSet fs = new SimpleFieldSet(br, false, true);
+               br.close();
+               // Read contents
+               String[] udp = fs.getAll("physical.udp");
+               if((udp != null) && (udp.length > 0)) {
+                       for(int i=0;i<udp.length;i++) {
+                               // Just keep the first one with the correct 
port number.
+                               Peer p;
+                               try {
+                                       p = new Peer(udp[i], false);
+                               } catch (PeerParseException e) {
+                                       IOException e1 = new IOException();
+                                       e1.initCause(e);
+                                       throw e1;
+                               }
+                               if(p.getPort() == crypto.portNumber) {
+                                       // DNSRequester doesn't deal with our 
own node
+                                       
node.ipDetector.setOldIPAddress(p.getFreenetAddress());
+                                       break;
+                               }
+                       }
+               }
+               
+               crypto.readCrypto(fs);
+       }
+
+       public void start() {
+               // FIXME do something
+       }
+
+       /**
+        * Called when opennet is disabled
+        */
+       public void stop() {
+               // FIXME do something
+       }
+
+}

Added: trunk/freenet/src/freenet/node/OpennetPeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/OpennetPeerNode.java                         
(rev 0)
+++ trunk/freenet/src/freenet/node/OpennetPeerNode.java 2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -0,0 +1,17 @@
+package freenet.node;
+
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.support.SimpleFieldSet;
+
+public class OpennetPeerNode extends PeerNode {
+
+       public OpennetPeerNode(SimpleFieldSet fs, Node node2, NodeCrypto 
crypto, PeerManager peers, boolean fromLocal, OutgoingPacketMangler mangler) 
throws FSParseException, PeerParseException, 
ReferenceSignatureVerificationException {
+               super(fs, node2, crypto, peers, fromLocal, mangler);
+       }
+
+       public PeerNodeStatus getStatus() {
+               return new OpennetPeerNodeStatus(this);
+       }
+
+}

Added: trunk/freenet/src/freenet/node/OpennetPeerNodeStatus.java
===================================================================
--- trunk/freenet/src/freenet/node/OpennetPeerNodeStatus.java                   
        (rev 0)
+++ trunk/freenet/src/freenet/node/OpennetPeerNodeStatus.java   2007-06-29 
17:30:56 UTC (rev 13823)
@@ -0,0 +1,9 @@
+package freenet.node;
+
+public class OpennetPeerNodeStatus extends PeerNodeStatus {
+
+       OpennetPeerNodeStatus(PeerNode peerNode) {
+               super(peerNode);
+       }
+
+}

Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java     2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/PeerManager.java     2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -52,7 +52,8 @@
     /** All the peers we are actually connected to */
     PeerNode[] connectedPeers;

-    final String filename;
+    private String darkFilename;
+    private String openFilename;

     private PeerManagerUserAlert ua;

@@ -93,16 +94,26 @@
      * @param node
      * @param filename
      */
-    public PeerManager(Node node, NodeCrypto crypto, String filename, 
OutgoingPacketMangler mangler) {
+    public PeerManager(Node node) {
         Logger.normal(this, "Creating PeerManager");
         logMINOR = Logger.shouldLog(Logger.MINOR, this);
                peerNodeStatuses = new HashMap();
                peerNodeRoutingBackoffReasons = new HashMap();
         System.out.println("Creating PeerManager");
-        this.filename = filename;
         myPeers = new PeerNode[0];
         connectedPeers = new PeerNode[0];
         this.node = node;
+    }
+
+    void tryReadPeers(String filename, NodeCrypto crypto, boolean isOpennet) {
+       synchronized(writePeersSync) {
+               if(isOpennet) {
+                       openFilename = filename;
+               } else {
+                       darkFilename = filename;
+               }
+       }
+       OutgoingPacketMangler mangler = crypto.packetMangler;
         File peersFile = new File(filename);
         File backupFile = new File(filename+".bak");
         // Try to read the node list from disk
@@ -125,9 +136,9 @@
                        System.err.println("No (readable) peers file with peers 
in it found");
                }
        }               
-    }
+       }

-    private boolean readPeers(File peersFile, OutgoingPacketMangler mangler, 
NodeCrypto crypto) {
+       private boolean readPeers(File peersFile, OutgoingPacketMangler 
mangler, NodeCrypto crypto) {
        boolean gotSome = false;
        FileInputStream fis;
                try {
@@ -172,7 +183,7 @@
         try {
                br.close();
         } catch (IOException e3) {
-               Logger.error(this, "Ignoring "+e3+" caught reading "+filename, 
e3);
+               Logger.error(this, "Ignoring "+e3+" caught reading "+peersFile, 
e3);
         }
         return gotSome;
        }
@@ -727,11 +738,20 @@
                        }
        }, 0);
     }
+
+    private void writePeersInner() {
+       synchronized(writePeersSync) {
+               if(darkFilename != null)
+                       writePeersInner(darkFilename, getDarknetPeers());
+               if(openFilename != null)
+                       writePeersInner(openFilename, getOpennetPeers());
+       }
+    }

     /**
      * Write the peers file to disk
      */
-    private void writePeersInner() {
+    private void writePeersInner(String filename, PeerNode[] peers) {
         synchronized (writePeersSync) {
             FileOutputStream fos;
             String f = filename + ".bak";
@@ -750,7 +770,7 @@
                        }
             BufferedWriter bw = new BufferedWriter(w);
             try {
-               boolean succeeded = writePeers(bw);
+               boolean succeeded = writePeers(bw, peers);
                 bw.close();
                 if(!succeeded) return;
             } catch (IOException e) {
@@ -762,9 +782,10 @@
                 Logger.error(this, "Cannot write file: " + e, e);
                 return; // don't overwrite old file!
             }
-            if (!new File(f).renameTo(new File(filename))) {
-                new File(filename).delete();
-                if (!new File(f).renameTo(new File(filename))) {
+            File fnam = new File(filename);
+            if (!new File(f).renameTo(fnam)) {
+                fnam.delete();
+                if (!new File(f).renameTo(fnam)) {
                     Logger.error(this, "Could not rename " + f + " to "
                             + filename + " writing peers");
                 }
@@ -772,11 +793,13 @@
         }
     }

-       public boolean writePeers(Writer bw) {
-        PeerNode[] peers;
-        synchronized (this) {
-                       peers = myPeers;
-               }
+    public boolean writePeers(Writer bw) {
+       if(!writePeers(bw, getDarknetPeers())) return false;
+       if(!writePeers(bw, getOpennetPeers())) return false;
+       return true;
+    }
+    
+       public boolean writePeers(Writer bw, PeerNode[] peers) {
         for (int i = 0; i < peers.length; i++) {
             try {
                 peers[i].write(bw);
@@ -1114,6 +1137,15 @@
                return peerNodeStatuses;
        }

+       public OpennetPeerNodeStatus[] getOpennetPeerNodeStatuses() {
+        OpennetPeerNode[] peers = getOpennetPeers();
+               OpennetPeerNodeStatus[] peerNodeStatuses = new 
OpennetPeerNodeStatus[peers.length];
+               for (int peerIndex = 0, peerCount = peers.length; peerIndex < 
peerCount; peerIndex++) {
+                       peerNodeStatuses[peerIndex] = (OpennetPeerNodeStatus) 
peers[peerIndex].getStatus();
+               }
+               return peerNodeStatuses;
+       }
+
        /**
         * Update hadRoutableConnectionCount/routableConnectionCheckCount on 
peers if the timer has expired
         */
@@ -1133,6 +1165,7 @@

        /**
         * Get the darknet peers list.
+        * FIXME: optimise
         */
        public DarknetPeerNode[] getDarknetPeers() {
                PeerNode[] peers;
@@ -1148,4 +1181,20 @@
                return (DarknetPeerNode[])v.toArray(new 
DarknetPeerNode[v.size()]);
        }

+       /**
+        * Get the opennet peers list.
+        */
+       public OpennetPeerNode[] getOpennetPeers() {
+               PeerNode[] peers;
+               synchronized(this) {
+                       peers = myPeers;
+               }
+               // FIXME optimise! Maybe maintain as a separate list?
+               Vector v = new Vector(myPeers.length);
+               for(int i=0;i<peers.length;i++) {
+                       if(peers[i] instanceof OpennetPeerNode)
+                               v.add(peers[i]);
+               }
+               return (OpennetPeerNode[])v.toArray(new 
OpennetPeerNode[v.size()]);
+       }
 }

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -2648,7 +2648,10 @@
         * Create a DarknetPeerNode or an OpennetPeerNode as appropriate
         */
        public static PeerNode create(SimpleFieldSet fs, Node node2, NodeCrypto 
crypto, PeerManager manager, boolean b, OutgoingPacketMangler mangler) throws 
FSParseException, PeerParseException, ReferenceSignatureVerificationException {
-               return new DarknetPeerNode(fs, node2, crypto, manager, b, 
mangler);
+               if(crypto.isOpennet)
+                       return new OpennetPeerNode(fs, node2, crypto, manager, 
b, mangler);
+               else
+                       return new DarknetPeerNode(fs, node2, crypto, manager, 
b, mangler);
        }

        public byte[] getIdentity() {

Modified: trunk/freenet/src/freenet/node/TestnetHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/TestnetHandler.java  2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/TestnetHandler.java  2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -177,9 +177,14 @@
                                        if(logMINOR) Logger.minor(this, 
"Sending references");
                                        OutputStreamWriter osw = new 
OutputStreamWriter(os, "ISO-8859-1");
                                        BufferedWriter bw = new 
BufferedWriter(osw);
-                                       bw.write("My ref:\n\n");
-                                       SimpleFieldSet fs = 
node.exportPublicFieldSet();
+                                       bw.write("My darknet ref:\n\n");
+                                       SimpleFieldSet fs = 
node.exportDarknetPublicFieldSet();
                                        fs.writeTo(bw);
+                                       if(node.isOpennetEnabled()) {
+                                               bw.write("My opennet ref:\n\n");
+                                               fs = 
node.exportOpennetPublicFieldSet();
+                                               fs.writeTo(bw);
+                                       }
                                        bw.write("\n\nMy peers:\n");
                                        node.peers.writePeers(bw);
                                        bw.close();

Modified: trunk/freenet/src/freenet/node/TestnetStatusUploader.java
===================================================================
--- trunk/freenet/src/freenet/node/TestnetStatusUploader.java   2007-06-29 
16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/node/TestnetStatusUploader.java   2007-06-29 
17:30:56 UTC (rev 13823)
@@ -55,7 +55,7 @@
                                        client = new 
Socket("emu.freenetproject.org", 23415);
                                        PrintStream output = new 
PrintStream(client.getOutputStream());

-                                       
output.println(node.exportPublicFieldSet().toString());
+                                       
output.println(node.exportDarknetPublicFieldSet().toString());
                                        output.println();
                                        output.println(node.getFreevizOutput());
                                        output.close();

Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2007-06-29 
16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2007-06-29 
17:30:56 UTC (rev 13823)
@@ -647,8 +647,14 @@
                        }

         } else if(uline.startsWith("STATUS")) {
-            SimpleFieldSet fs = n.exportPublicFieldSet();
+               outsb.append("DARKNET:\n");
+            SimpleFieldSet fs = n.exportDarknetPublicFieldSet();
             outsb.append(fs.toString());
+            if(n.isOpennetEnabled()) {
+               outsb.append("OPENNET:\n");
+               fs = n.exportOpennetPublicFieldSet();
+                outsb.append(fs.toString());
+            }
             outsb.append(n.getStatus());
             if(Version.buildNumber()<Version.highestSeenBuild){
                 outsb.append("The latest version is : 
").append(Version.highestSeenBuild);

Modified: trunk/freenet/src/freenet/node/fcp/NodeData.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/NodeData.java    2007-06-29 16:11:36 UTC 
(rev 13822)
+++ trunk/freenet/src/freenet/node/fcp/NodeData.java    2007-06-29 17:30:56 UTC 
(rev 13823)
@@ -22,9 +22,9 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs;
                if(withPrivate) {
-                       fs = node.exportPrivateFieldSet();
+                       fs = node.exportDarknetPublicFieldSet();
                } else {
-                       fs = node.exportPublicFieldSet();
+                       fs = node.exportDarknetPrivateFieldSet();
                }
                if(withVolatile) {
                        SimpleFieldSet vol = node.exportVolatileFieldSet();

Modified: 
trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java     
2007-06-29 16:11:36 UTC (rev 13822)
+++ trunk/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java     
2007-06-29 17:30:56 UTC (rev 13823)
@@ -56,7 +56,7 @@
         }
         SimpleFieldSet refs[] = new SimpleFieldSet[NUMBER_OF_NODES];
         for(int i=0;i<NUMBER_OF_NODES;i++)
-            refs[i] = nodes[i].exportPublicFieldSet();
+            refs[i] = nodes[i].exportDarknetPublicFieldSet();
         Logger.normal(RealNodeRoutingTest.class, "Created "+NUMBER_OF_NODES+" 
nodes");
         // Now link them up
         // Connect the set


Reply via email to