Skip to content

Instantly share code, notes, and snippets.

@hannahherbig
Created January 24, 2013 05:32
Show Gist options
  • Save hannahherbig/4617916 to your computer and use it in GitHub Desktop.
Save hannahherbig/4617916 to your computer and use it in GitHub Desktop.
a dead simple torrent tracker in ruby
require 'bencode'
require 'sinatra'
torrents = {}
get '/announce' do
compact = (params[:compact] || '1') == '1'
no_peer_id = params[:no_peer_id] == '1'
event = params[:event] || 'empty'
numwant = (request[:numwant] || 50).to_i
complete = params[:left].to_i == 0
torrents[params[:info_hash]] ||= { peers: {}, snatches: 0 }
pcomplete = 0
pincomplete = 0
peerids = torrents[params[:info_hash]][:peers].keys.shuffle
peerlist = compact ? '' : []
while numwant > 0 and not peerids.empty?
peerid = peerids.shift
peer = torrents[params[:info_hash]][:peers][peerid]
unless complete and peer[:complete]
if compact
peerlist << (peer[:ip].split('.').map(&:to_i) + [peer[:port]]).pack('CCCCS>')
else
peer = {
'ip' => peer[:ip],
'port' => peer[:port]
}
peer['peer id'] = peerid unless no_peer_id
end
numwant -= 1
end
if peer[:complete]
pcomplete += 1
else
pincomplete += 1
end
end
torrents[params[:info_hash]][:peers][params[:peer_id]] = {
ip: params[:ip] || request.ip,
port: params[:port].to_i,
complete: complete
}
torrents[params[:info_hash]][:snatches] += 1 if event == 'complete'
puts "#{params[:info_hash].unpack('H*').first} #{pcomplete} #{pincomplete}"
{
'interval' => 10,
'min interval' => 1,
'complete' => pcomplete,
'incomplete' => pincomplete,
'peers' => peerlist
}.bencode
end
get '/scrape' do
files = {}
(params[:info_hash] ? [params[:info_hash]] : torrents.keys).each do |info_hash|
t = torrents[info_hash]
files[info_hash] = {
complete: t[:peers].values.count { |p| p[:complete] },
downloaded: t[:snatches],
incomplete: t[:peers].values.count { |p| not p[:complete] }
}
end
files.each do |i, t|
puts "#{i.unpack('H*').first} downloaded=#{t[:downloaded]} complete=#{t[:complete]} incomplete=#{t[:incomplete]}"
end
{ files: files }.bencode
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment