From 1f569b7359ee31f54659bf695c70ce56362088c4 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Thu, 7 Dec 2017 19:44:56 +0000
Subject: [PATCH] i2psnark: Synch operations on BitField byte array

---
 .../java/src/org/klomp/snark/BitField.java    |  2 ++
 .../org/klomp/snark/PeerConnectionOut.java    | 20 +++++++++++++++---
 .../src/org/klomp/snark/SnarkManager.java     | 21 +++++++++++--------
 3 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/apps/i2psnark/java/src/org/klomp/snark/BitField.java b/apps/i2psnark/java/src/org/klomp/snark/BitField.java
index 3534a8d7ee..b67ab86223 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/BitField.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/BitField.java
@@ -71,6 +71,8 @@ public class BitField
    * affect this BitField.  Note that some bits at the end of the byte
    * array are supposed to be always unset if they represent bits
    * bigger then the size of the bitfield.
+   *
+   * Caller should synch on this and copy!
    */
   public byte[] getFieldBytes()
   {
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
index 8cca67e8e7..b12bf5d883 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
@@ -22,6 +22,7 @@ package org.klomp.snark;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
@@ -355,12 +356,25 @@ class PeerConnectionOut implements Runnable
   void sendBitfield(BitField bitfield)
   {
     boolean fast = peer.supportsFast();
-    if (fast && bitfield.complete()) {
+    boolean all = false;
+    boolean none = false;
+    byte[] data = null;
+    synchronized(bitfield) {
+        if (fast && bitfield.complete()) {
+            all = true;
+        } else if (fast && bitfield.count() <= 0) {
+            none = true;
+        } else {
+           byte[] d = bitfield.getFieldBytes();
+           data =  Arrays.copyOf(d, d.length);
+        }
+    }
+    if (all) {
         sendHaveAll();
-    } else if (fast && bitfield.count() <= 0) {
+    } else if (none) {
         sendHaveNone();
     } else {
-       Message m = new Message(bitfield.getFieldBytes());
+       Message m = new Message(data);
        addMessage(m);
     }
   }
diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
index 6d612e2bb7..69ca276c42 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
@@ -1671,7 +1671,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
         }
         if (autoStart) {
             startTorrent(ih);
-            addMessage(_t("Fetching {0}", name));
+            if (false)
+                addMessage(_t("Fetching {0}", name));
             DHT dht = _util.getDHT();
             boolean shouldWarn = _util.connected() &&
                                  _util.getOpenTrackers().isEmpty() &&
@@ -2053,14 +2054,16 @@ public class SnarkManager implements CompleteListener, ClientApp {
         if (config.getProperty(PROP_META_ADDED) == null)
             config.setProperty(PROP_META_ADDED, now);
         String bfs;
-        if (bitfield.complete()) {
-          bfs = ".";
-          if (config.getProperty(PROP_META_COMPLETED) == null)
-              config.setProperty(PROP_META_COMPLETED, now);
-        } else {
-          byte[] bf = bitfield.getFieldBytes();
-          bfs = Base64.encode(bf);
-          config.remove(PROP_META_COMPLETED);
+        synchronized(bitfield) {
+            if (bitfield.complete()) {
+              bfs = ".";
+              if (config.getProperty(PROP_META_COMPLETED) == null)
+                  config.setProperty(PROP_META_COMPLETED, now);
+            } else {
+              byte[] bf = bitfield.getFieldBytes();
+              bfs = Base64.encode(bf);
+              config.remove(PROP_META_COMPLETED);
+            }
         }
         config.setProperty(PROP_META_BITFIELD, bfs);
         config.setProperty(PROP_META_PRESERVE_NAMES, Boolean.toString(preserveNames));
-- 
GitLab