From 01b67acfa017ef92e5215431396b1f8c4b56a2a8 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Tue, 28 Dec 2010 15:46:45 +0000
Subject: [PATCH] - Catch OOM when creating torrent (tickets #364 and #366) -
 Fix changing 'use open trackers' config setting (old bug) - More
 TrackerClient fixes for no primary announce - More BEValue.toString()
 improvements for debugging

---
 .../src/org/klomp/snark/I2PSnarkUtil.java     | 15 +++++---
 .../java/src/org/klomp/snark/Snark.java       |  2 +
 .../src/org/klomp/snark/SnarkManager.java     |  7 +++-
 .../src/org/klomp/snark/TrackerClient.java    | 10 ++---
 .../src/org/klomp/snark/bencode/BEValue.java  | 37 +++++++++++++++----
 .../org/klomp/snark/web/I2PSnarkServlet.java  |  2 +
 6 files changed, 53 insertions(+), 20 deletions(-)

diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
index 775d4cc4ab..16edc12f65 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
@@ -60,6 +60,7 @@ public class I2PSnarkUtil {
     private int _maxConnections;
     private File _tmpDir;
     private int _startupDelay;
+    private boolean _shouldUseOT;
     private KRPC _krpc;
 
     public static final int DEFAULT_STARTUP_DELAY = 3;
@@ -83,6 +84,7 @@ public class I2PSnarkUtil {
         _maxUpBW = DEFAULT_MAX_UP_BW;
         _maxConnections = MAX_CONNECTIONS;
         _startupDelay = DEFAULT_STARTUP_DELAY;
+        _shouldUseOT = DEFAULT_USE_OPENTRACKERS;
         // This is used for both announce replies and .torrent file downloads,
         // so it must be available even if not connected to I2CP.
         // so much for multiple instances
@@ -425,10 +427,10 @@ public class I2PSnarkUtil {
 
     /** comma delimited list open trackers to use as backups */
     /** sorted map of name to announceURL=baseURL */
-    public List getOpenTrackers() { 
+    public List<String> getOpenTrackers() { 
         if (!shouldUseOpenTrackers())
             return null;
-        List rv = new ArrayList(1);
+        List<String> rv = new ArrayList(1);
         String trackers = getOpenTrackerString();
         StringTokenizer tok = new StringTokenizer(trackers, ", ");
         while (tok.hasMoreTokens())
@@ -439,11 +441,12 @@ public class I2PSnarkUtil {
         return rv;
     }
     
+    public void setUseOpenTrackers(boolean yes) {
+        _shouldUseOT = yes;
+    }
+
     public boolean shouldUseOpenTrackers() {
-        String rv = (String) _opts.get(PROP_USE_OPENTRACKERS);
-        if (rv == null)
-            return DEFAULT_USE_OPENTRACKERS;
-        return Boolean.valueOf(rv).booleanValue();
+        return _shouldUseOT;
     }
 
     /**
diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java
index d114fe0ee2..e3a99bdc9b 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java
@@ -394,6 +394,8 @@ public class Snark
          */
         else
           fatal("Cannot open '" + torrent + "'", ioe);
+      } catch (OutOfMemoryError oom) {
+          fatal("ERROR - Out of memory, cannot create torrent " + torrent + ": " + oom.getMessage());
       } finally {
           if (in != null)
               try { in.close(); } catch (IOException ioe) {}
diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
index 1e5ba10bf2..6ac7261e3e 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
@@ -263,7 +263,9 @@ public class SnarkManager implements Snark.CompleteListener {
         String ot = _config.getProperty(I2PSnarkUtil.PROP_OPENTRACKERS);
         if (ot != null)
             _util.setOpenTrackerString(ot);
-        // FIXME set util use open trackers property somehow
+        String useOT = _config.getProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS);
+        boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
+        _util.setUseOpenTrackers(bOT);
         getDataDir().mkdirs();
     }
     
@@ -434,6 +436,7 @@ public class SnarkManager implements Snark.CompleteListener {
                 addMessage(_("Enabled open trackers - torrent restart required to take effect."));
             else
                 addMessage(_("Disabled open trackers - torrent restart required to take effect."));
+            _util.setUseOpenTrackers(useOpenTrackers);
             changed = true;
         }
         if (openTrackers != null) {
@@ -605,6 +608,8 @@ public class SnarkManager implements Snark.CompleteListener {
                     if (sfile.exists())
                         sfile.delete();
                     return;
+                } catch (OutOfMemoryError oom) {
+                    addMessage(_("ERROR - Out of memory, cannot create torrent from {0}", sfile.getName()) + ": " + oom.getMessage());
                 } finally {
                     if (fis != null) try { fis.close(); } catch (IOException ioe) {}
                 }
diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
index d03753d6bd..9cf9f7f097 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
@@ -137,18 +137,18 @@ public class TrackerClient extends I2PAppThread
     // the primary tracker, that we don't add it twice.
     // todo: check for b32 matches as well
     trackers = new ArrayList(2);
-    String primary;
+    String primary = null;
     if (meta != null) {
         primary = meta.getAnnounce();
         if (isValidAnnounce(primary)) {
             trackers.add(new Tracker(meta.getAnnounce(), true));
+            _log.debug("Announce: [" + primary + "] infoHash: " + infoHash);
         } else {
             _log.warn("Skipping invalid or non-i2p announce: " + primary);
         }
-    } else {
-        primary = "";
     }
-    _log.debug("Announce: [" + primary + "] infoHash: " + infoHash);
+    if (primary == null)
+        primary = "";
     List tlist = _util.getOpenTrackers();
     if (tlist != null) {
         for (int i = 0; i < tlist.size(); i++) {
@@ -179,7 +179,7 @@ public class TrackerClient extends I2PAppThread
         }
     }
 
-    if (tlist.isEmpty()) {
+    if (trackers.isEmpty()) {
         // FIXME really need to get this message to the gui
         stop = true;
         _log.error("No valid trackers for infoHash: " + infoHash);
diff --git a/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java b/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java
index 75a63bab19..4cae2881ae 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java
@@ -180,15 +180,36 @@ public class BEValue
     String valueString;
     if (value instanceof byte[])
       {
+        // try to do a nice job for debugging
         byte[] bs = (byte[])value;
-        // XXX - Stupid heuristic... and not UTF-8
-        //if (bs.length <= 12)
-        //  valueString = new String(bs);
-        //else
-        //  valueString = "bytes:" + bs.length;
-        if (bs.length <= 32)
-          valueString =  bs.length + " bytes: " + Base64.encode(bs);
-        else
+        if (bs.length == 0)
+          valueString =  "0 bytes";
+        else if (bs.length <= 32) {
+          StringBuilder buf = new StringBuilder(32);
+          boolean bin = false;
+          for (int i = 0; i < bs.length; i++) {
+              int b = bs[i] & 0xff;
+              // no UTF-8
+              if (b < ' ' || b > 0x7e) {
+                  bin = true;
+                  break;
+              }
+          }
+          if (bin && bs.length <= 8) {
+              buf.append(bs.length).append(" bytes: 0x");
+              for (int i = 0; i < bs.length; i++) {
+                  int b = bs[i] & 0xff;
+                  if (b < 16)
+                      buf.append('0');
+                  buf.append(Integer.toHexString(b));
+              }
+          } else if (bin) {
+              buf.append(bs.length).append(" bytes: ").append(Base64.encode(bs));
+          } else {
+              buf.append('"').append(new String(bs)).append('"');
+          }
+          valueString = buf.toString();
+        } else
           valueString =  bs.length + " bytes";
       }
     else
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index 6b82734555..5890c0df65 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -1902,6 +1902,8 @@ private static class FetchAndAdd implements Runnable {
                     }
                 } catch (IOException ioe) {
                     _manager.addMessage(_("Torrent at {0} was not valid", urlify(_url)) + ": " + ioe.getMessage());
+                } catch (OutOfMemoryError oom) {
+                    _manager.addMessage(_("ERROR - Out of memory, cannot create torrent from {0}", urlify(_url)) + ": " + oom.getMessage());
                 } finally {
                     try { if (in != null) in.close(); } catch (IOException ioe) {}
                 }
-- 
GitLab