From fea6b8aec3db026385d7ec7daef554470035922b Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Sat, 25 Jul 2015 13:15:56 +0000
Subject: [PATCH] i2psnark: Fix total_size in metadata message (ticket #1618)

---
 .../src/org/klomp/snark/ExtensionHandler.java | 27 +++++++++++--------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java b/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java
index 1835ffe90c..53247a6991 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java
@@ -207,30 +207,31 @@ abstract class ExtensionHandler {
                 if (log.shouldLog(Log.DEBUG))
                     log.debug("Got request for " + piece + " from: " + peer);
                 byte[] pc;
+                int totalSize;
                 synchronized(state) {
                     pc = state.getChunk(piece);
+                    totalSize = state.getSize();
                 }
-                sendPiece(peer, piece, pc);
+                sendPiece(peer, piece, pc, totalSize);
                 // Do this here because PeerConnectionOut only reports for PIECE messages
                 peer.uploaded(pc.length);
                 listener.uploaded(peer, pc.length);
             } else if (type == TYPE_DATA) {
-                int size = map.get("total_size").getInt();
-                if (log.shouldLog(Log.DEBUG))
-                    log.debug("Got data for " + piece + " length " + size + " from: " + peer);
+                // On close reading of BEP 9, this is the total metadata size.
+                // Prior to 0.9.21, we sent the piece size, so we can't count on it.
+                // just ignore it. The actual length will be verified in saveChunk()
+                //int size = map.get("total_size").getInt();
+                //if (log.shouldLog(Log.DEBUG))
+                //    log.debug("Got data for " + piece + " length " + size + " from: " + peer);
                 boolean done;
                 int chk = -1;
                 synchronized(state) {
                     if (state.isComplete())
                         return;
                     int len = is.available();
-                    if (len != size) {
-                        // probably fatal
-                        if (log.shouldLog(Log.WARN))
-                            log.warn("total_size " + size + " but avail data " + len);
-                    }
                     peer.downloaded(len);
                     listener.downloaded(peer, len);
+                    // this checks the size
                     done = state.saveChunk(piece, bs, bs.length - len, len);
                     if (log.shouldLog(Log.INFO))
                         log.info("Got chunk " + piece + " from " + peer);
@@ -293,11 +294,15 @@ abstract class ExtensionHandler {
         }
     }
 
-    private static void sendPiece(Peer peer, int piece, byte[] data) {
+    private static void sendPiece(Peer peer, int piece, byte[] data, int totalSize) {
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("msg_type", Integer.valueOf(TYPE_DATA));
         map.put("piece", Integer.valueOf(piece));
-        map.put("total_size", Integer.valueOf(data.length));
+        // BEP 9
+        // "This key has the same semantics as the 'metadata_size' in the extension header"
+        // which apparently means the same value. Fixed in 0.9.21.
+        //map.put("total_size", Integer.valueOf(data.length));
+        map.put("total_size", Integer.valueOf(totalSize));
         byte[] dict = BEncoder.bencode(map);
         byte[] payload = new byte[dict.length + data.length];
         System.arraycopy(dict, 0, payload, 0, dict.length);
-- 
GitLab