From 071498c413a3e643b5a86be5763d61a88127a673 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Mon, 16 Mar 2015 15:10:36 +0000
Subject: [PATCH] Router: Republish RI early if capabilities change - RI
 javadoc clarifications WRT caps

---
 .../src/net/i2p/data/router/RouterInfo.java   |  4 ++
 .../networkdb/PublishLocalRouterInfoJob.java  | 46 +++++++++++--------
 2 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/router/java/src/net/i2p/data/router/RouterInfo.java b/router/java/src/net/i2p/data/router/RouterInfo.java
index 6dbff55cd7..cb977a8648 100644
--- a/router/java/src/net/i2p/data/router/RouterInfo.java
+++ b/router/java/src/net/i2p/data/router/RouterInfo.java
@@ -286,6 +286,8 @@ public class RouterInfo extends DatabaseEntry {
      * Configure a set of options or statistics that the router can expose.
      * Makes a copy.
      *
+     * Warning, clears all capabilities, must be called BEFORE addCapability().
+     *
      * @param options if null, clears current options
      * @throws IllegalStateException if RouterInfo is already signed
      */
@@ -433,6 +435,8 @@ public class RouterInfo extends DatabaseEntry {
     }
 
     /**
+     * Warning, must be called AFTER setOptions().
+     *
      * @throws IllegalStateException if RouterInfo is already signed
      */
     public void addCapability(char cap) {
diff --git a/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java b/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java
index 5a561a1071..d6c0685883 100644
--- a/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java
+++ b/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java
@@ -81,39 +81,47 @@ public class PublishLocalRouterInfoJob extends JobImpl {
             List<RouterAddress> oldAddrs = new ArrayList<RouterAddress>(oldRI.getAddresses());
             List<RouterAddress> newAddrs = getContext().commSystem().createAddresses();
             int count = _runCount.incrementAndGet();
+            RouterInfo ri = new RouterInfo(oldRI);
+            // this will get overwritten by setOptions() below, must restore it below
+            getContext().router().addCapabilities(ri);
+            String caps = ri.getCapabilities();
             if (_notFirstTime && (count % 4) != 0 && oldAddrs.size() == newAddrs.size()) {
                 // 3 times out of 4, we don't republish if everything is the same...
                 // If something changed, including the cost, then publish,
                 // otherwise don't.
-                boolean different = false;
-                Comparator<RouterAddress> comp = new AddrComparator();
-                Collections.sort(oldAddrs, comp);
-                Collections.sort(newAddrs, comp);
-                for (int i = 0; i < oldAddrs.size(); i++) {
-                    // deepEquals() includes cost
-                    if (!oldAddrs.get(i).deepEquals(newAddrs.get(i))) {
-                        different = true;
-                        break;
-                    }
-                }
+                boolean different = !oldRI.getCapabilities().equals(ri.getCapabilities());
                 if (!different) {
-                    if (_log.shouldLog(Log.INFO))
-                        _log.info("Not republishing early because costs are the same");
-                    requeue(getDelay());
-                    return;
+                    Comparator<RouterAddress> comp = new AddrComparator();
+                    Collections.sort(oldAddrs, comp);
+                    Collections.sort(newAddrs, comp);
+                    for (int i = 0; i < oldAddrs.size(); i++) {
+                        // deepEquals() includes cost
+                        if (!oldAddrs.get(i).deepEquals(newAddrs.get(i))) {
+                            different = true;
+                            break;
+                        }
+                    }
+                    if (!different) {
+                        if (_log.shouldLog(Log.INFO))
+                            _log.info("Not republishing early because costs and caps and addresses are the same");
+                        requeue(getDelay());
+                        return;
+                    }
                 }
                 if (_log.shouldLog(Log.INFO))
-                    _log.info("Republishing early because addresses or costs have changed - old:\n" +
+                    _log.info("Republishing early because addresses or costs or caps have changed -" +
+                              " oldCaps: " + oldRI.getCapabilities() + " newCaps: " + ri.getCapabilities() +
+                              " old:\n" +
                               oldAddrs + "\nnew:\n" + newAddrs);
             }
-            RouterInfo ri = new RouterInfo(oldRI);
             ri.setPublished(getContext().clock().now());
             Properties stats = getContext().statPublisher().publishStatistics();
-            stats.setProperty(RouterInfo.PROP_NETWORK_ID, ""+Router.NETWORK_ID);
+            stats.setProperty(RouterInfo.PROP_NETWORK_ID, String.valueOf(Router.NETWORK_ID));
+            // restore caps generated above
+            stats.setProperty(RouterInfo.PROP_CAPABILITIES, caps);
             ri.setOptions(stats);
             ri.setAddresses(newAddrs);
 
-            getContext().router().addCapabilities(ri);
             SigningPrivateKey key = getContext().keyManager().getSigningPrivateKey();
             if (key == null) {
                 _log.log(Log.CRIT, "Internal error - signing private key not known?  rescheduling publish for 30s");
-- 
GitLab