summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Hahn <sebastian@torproject.org>2009-08-11 13:43:06 +0200
committerSebastian Hahn <sebastian@torproject.org>2009-08-25 20:10:25 +0200
commitaa0d32f4b675e155e6e004604bf8b6ee4e607873 (patch)
tree110c9722f93380497447c54bf07f4227f11b7206
parent6ebc7d6103098e695c33f55f84e6f64f5d795e84 (diff)
Add ability to create .torrent metadata when making a package
Also update the spec with the information where the .torrent metadata file will be stored.
-rw-r--r--doc/HOWTO3
-rw-r--r--lib/thandy/SignerCLI.py14
-rw-r--r--lib/thandy/bt_compat.py76
-rw-r--r--lib/thandy/master_keys.py3
-rw-r--r--specs/thandy-spec.txt6
5 files changed, 101 insertions, 1 deletions
diff --git a/doc/HOWTO b/doc/HOWTO
index a5937f3..4ec6068 100644
--- a/doc/HOWTO
+++ b/doc/HOWTO
@@ -217,7 +217,8 @@ and notes:
* For the actual data files (i.e. the packages themselves), for now you
just copy them into the repository manually. Later there will be some
- version of thandy-server insert that handles them too.
+ version of thandy-server insert that handles them too. The same goes
+ for the BitTorrent metadata files.
.GENERATING TIMESTAMPS.
diff --git a/lib/thandy/SignerCLI.py b/lib/thandy/SignerCLI.py
index d0feef6..06536aa 100644
--- a/lib/thandy/SignerCLI.py
+++ b/lib/thandy/SignerCLI.py
@@ -7,6 +7,7 @@ import sys
import thandy.keys
import thandy.formats
import thandy.util
+import thandy.bt_compat
json = thandy.util.importJSON()
@@ -78,6 +79,19 @@ def makepackage(args):
f = open(location, 'w')
json.dump(signable, f, indent=1, sort_keys=True)
f.close()
+ btcomp = thandy.bt_compat.BtCompat()
+ # If we have bittorrent support, we always create the appropriate metadata.
+ thandy.bt_compat.BtCompat.setUseBt(True)
+ if not thandy.bt_compat.BtCompat.shouldUseBt():
+ print "Not generating BitTorrent metadata files"
+ return
+ print "Generating BitTorrent metadata file"
+ metaFile = btcomp.makeMetaFile(dataFile)
+ mfLocation = os.path.split(btcomp.getBtMetadataLocation(location, dataFile))[-1]
+ print "Writing BitTorrent Metadata file to %s"%mfLocation
+ f = open(mfLocation, 'w')
+ f.write(metaFile)
+ f.close()
def makebundle(args):
options, args = getopt.getopt(args, "", "keyid=")
diff --git a/lib/thandy/bt_compat.py b/lib/thandy/bt_compat.py
new file mode 100644
index 0000000..43cecad
--- /dev/null
+++ b/lib/thandy/bt_compat.py
@@ -0,0 +1,76 @@
+# Copyright 2008 The Tor Project, Inc. See LICENSE for licensing information.
+
+import os.path
+import time
+
+import thandy.master_keys
+
+no_bt = None
+try:
+ import BitTorrent.bencode
+ import BitTorrent.btformats
+ import BitTorrent.download
+except ImportError:
+ no_bt = True
+from sha import sha # XXX Use PyCrypto here?
+
+
+class BtCompat:
+ """Interface for different bittorrent implementations"""
+
+ usingBt = False
+
+ def __init__(self):
+ self.tUrl = thandy.master_keys.DEFAULT_TRACKER
+ if not no_bt:
+ assert(self.tUrl is not None and self.tUrl != "")
+ self.pieceLength = 2 ** 18 # Piece length of 262144 bytes
+
+ # XXX Do we need to be thread-safe here and below?
+ @staticmethod
+ def shouldUseBt():
+ return BtCompat.usingBt
+
+ @staticmethod
+ def setUseBt(useBt):
+ if no_bt:
+ return
+ BtCompat.usingBt = useBt
+
+ @staticmethod
+ def getBtMetadataLocation(packagepath, filepath, pathprefix=""):
+ """Given a path for the package, the path for a file of that
+ package, and an optional prefix, return the path for the
+ .torrent metadata file. Always return Unix-like paths, to
+ ensure compatibility with fetching the path from a
+ webserver.
+ """
+ return (os.path.join(pathprefix, os.path.dirname(packagepath),
+ os.path.basename(filepath)) + ".torrent"
+ ).replace("\\", "/")
+
+ def makeMetaFile(self, file):
+ """Given a path to a file, create the contents of a .torrent
+ metadata file and return them.
+ """
+ size = os.path.getsize(file)
+ filename = os.path.basename(file)
+ pieces = []
+ p = 0
+ h = open(file, 'rb')
+ while p < size:
+ x = h.read(min(self.pieceLength, size - p))
+ pieces.append(sha(x).digest())
+ p += self.pieceLength
+ if p > size:
+ p = size
+ h.close()
+ info = {'pieces': ''.join(pieces),
+ 'piece length': self.pieceLength, 'length': size,
+ 'name': filename}
+ # Check we didn't screw up with the info
+ BitTorrent.btformats.check_info(info)
+ data = {'info': info, 'announce': self.tUrl,
+ 'creation date': long(time.time())}
+ return BitTorrent.bencode.bencode(data)
+
diff --git a/lib/thandy/master_keys.py b/lib/thandy/master_keys.py
index 05c50a8..be13f52 100644
--- a/lib/thandy/master_keys.py
+++ b/lib/thandy/master_keys.py
@@ -17,3 +17,6 @@ DEFAULT_MIRRORLIST = {
}
],
}
+
+DEFAULT_TRACKER = NONE
+
diff --git a/specs/thandy-spec.txt b/specs/thandy-spec.txt
index daadd05..eae908b 100644
--- a/specs/thandy-spec.txt
+++ b/specs/thandy-spec.txt
@@ -248,6 +248,12 @@
file that makes up a package, its hash, and what procedure
is used to install it.
+ /pkginfo/packagename/os-arch/version/(some filename).torrent
+
+ The .torrent metadata file used to download that file. The
+ file name is exactly the same as specified in the package
+ file.
+
/packages/packagename/os-arch/version/(some filename)
The actual package file. Its naming convention will depend