Hi, Background: bttrack.py is a open src torrent tracker, that uses
the option --dfile fileName, to save state information in. The file is
bencoded and has parts of it's content in binary. The encoding specs
and file format are described here:
http://wiki.theory.org/BitTorrentSpecification#lists
I am trying to write my own Perl script to create my own "dfile".
Data from a valid dstateFile (binary data has been converted to
ASCII):
d9:completedd20:.i.?.vk..&.7.....g..i0ee5:peersd20:.i.?.vk..&.
7.....g..
d20:-AZ2504-4PGqC1Tza6WDd2:ip9:127.0.0.13:key8:vkYZ3mwZ4:lefti12415246
5e3:nati0e4:porti35ee20:-
UT1740-..........#.d2:ip9:127.0.0.13:key8:29FA
43C64:lefti37137041e3:nati0e4:porti35eeeee
The above data when you interpret correctly (based on the
TorrentSpecs)forms a data structure like so:
{ 'completed' => { $shaHashBin => '0' }
'peers' => { $shaHashBin => { $clientID { ip => $ipAddr, key=>
$Key, left=>'0', nat=>'0', port=>$port}
$clientID2 { ip =>
$ipAddr, key=>$Key, left=>'0', nat=>'0', port=>$port}
}
}
}
Unfortunately for some reason $clientID is not being expanded properly
and instead of getting ClientID1/ClientID2/ClientID3 etc and their
associated ip/key/left/nat/port entries, all i get is a
single entry! I'm sure that the old records/entries are being
overwritten by the new entries - so I'm left with a perfectly valid
dstateFile with the last ip:port pair that was read from the file!
I also tried something like so:
$_=<IPFILE>;
chomp;
($ipAddr, $port) = split(/:/);
$clientID = RandomString(20);
$key = RandomString(8);
# dflist file structure.
<SNIP>
while (<IPFILE>) {
chomp;
($ipAddr, $port) = split(/:/);
$clientID = RandomString(20);
$key = RandomString(8);
$completedData->{'peers'}->{$clientID} =
MakeClientHash($ipAddr, $key, $port);
}
This works and the records don't get overwritten BUT the file format
is broken and i get data like so: d9:completedd20:.i.?.vk..&.
7.....g..i0ee5:peersd20:.i.?.vk..&.7.....g..d20:-AZ2504-4PGqC1Tza6WDd2:ip9:127.0.0.13:key8:vkYZ3mwZ4:lefti12415246
5e3:nati0e4:porti35eee20:-UT1740-..........#.d2:ip9:127.0.0.13:key8:29FA
43C64:lefti37137041e3:nati0e4:porti35eeee
Note the (eeee) That's }}}}. There should be 5 of them :( also note
eee20 - that should read ee20 :( Oh, and note: bencode breaks if the
torrentfile is complicated (just in case you actually debug
that).
----------------------------------------------------------
#!/usr/bin/perl
#
# Program to create a file called dflist that bttrack.py can
understand.
#use strict;
#use warnings;
use POSIX qw(strftime);
use Getopt::Std;
use URI::Escape 'uri_escape_utf8';
use Digest::SHA1 qw(sha1 sha1_hex sha1_base64);
use Convert::Bencode qw(bencode bdecode);
my ($torrentFile, $ipFile, $dflistFile);
my $debug=0;
(my $progname = $0) =~ s|.*/||;
sub UsageError() {
print STDERR "nusage: $progname torrentFile ipFile dfileNamen";
exit(2);
}
sub FatalError( $ ) {
print STDERR "$progname:
_n";
exit(1);
}
sub GetRunConfig() {
# If we have more than two arguments signal a error.
UsageError if (
ARGV != 3);
if (
ARGV == 3) { $torrentFile = $ARGV[0];
$ipFile = $ARGV[1];
$dflistFile = $ARGV[2]; }
}
sub ReadFile( $ ) {
my ($pathname) =
_;
local $/;
my $FH;
open($FH, '<', $pathname)
or FatalError("cannot open $pathname for reading: $!");
my $contents = <$FH>;
close $FH;
return $contents;
}
sub WriteFile(