class Torckapi::Tracker::UDP
Implementation of www.bittorrent.org/beps/bep_0015.html
Constants
- CONNECTION_TIMEOUT
- REQUEST_ACTIONS
- RESPONSE_CLASSES
- RESPONSE_CODES
- RESPONSE_MIN_LENGTHS
Public Class Methods
new(url, options={})
click to toggle source
Calls superclass method
Torckapi::Tracker::Base::new
# File lib/torckapi/tracker/udp.rb, line 28 def initialize url, options={} super @state = nil @connection_id = nil @communicated_at = 0 end
Public Instance Methods
announce(info_hash, peer_id=SecureRandom.random_bytes(20))
click to toggle source
Calls superclass method
Torckapi::Tracker::Base#announce
# File lib/torckapi/tracker/udp.rb, line 10 def announce info_hash, peer_id=SecureRandom.random_bytes(20) super perform_request Announce, announce_request_data(info_hash, peer_id), info_hash end
scrape(info_hashes=[])
click to toggle source
Calls superclass method
Torckapi::Tracker::Base#scrape
# File lib/torckapi/tracker/udp.rb, line 15 def scrape info_hashes=[] super perform_request Scrape, scrape_request_data(info_hashes), info_hashes end
Private Instance Methods
announce_request_data(info_hash, peer_id)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 49 def announce_request_data info_hash, peer_id [[info_hash].pack('H*'), peer_id, [0, 0, 0, 0, 0, 0, -1, 0].pack('Q>3L>4S>')].join end
check_response_length(response, response_code)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 113 def check_response_length response, response_code raise MalformedResponseError, response if RESPONSE_MIN_LENGTHS[response_code] > response.length end
check_transaction_id(response, transaction_id)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 99 def check_transaction_id response, transaction_id raise TransactionIdMismatchError, response if transaction_id != response[4..7] end
communicate(action, data=nil)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 65 def communicate action, data=nil @socket ||= UDPSocket.new tries = 0 response = nil begin timeout = @options[:timeout] * (2 ** tries) connect transaction_id = SecureRandom.random_bytes(4) packet = [@connection_id, [action].pack('L>'), transaction_id, data].join Timeout::timeout(timeout, CommunicationTimeoutError) do @socket.send(packet, 0, @url.host, @url.port) response = process_response @socket.recvfrom(65536)[0], transaction_id @communicated_at = Time.now end rescue CommunicationTimeoutError, LittleEndianResponseError => e retry if (tries += 1) <= @options[:tries] end raise CommunicationFailedError unless response response end
connect()
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 57 def connect return if connected? || connecting? @state, @connection_id = :connecting, [0x041727101980].pack('Q>') response = communicate Connect @state, @connection_id = nil, response[:data] end
connected?()
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 35 def connected? @connection_id && @communicated_at.to_i >= Time.now.to_i - CONNECTION_TIMEOUT end
connecting?()
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 39 def connecting? @state == :connecting end
extract_response_code(response)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 103 def extract_response_code response response_code, response_code_le = [response[0..3]].flat_map { |x| [x.unpack('L>')[0], x.unpack('L<')[0]] } unless RESPONSE_CODES.include?(response_code) raise (RESPONSE_CODES.include?(response_code_le) ? LittleEndianResponseError : MalformedResponseError), response end response_code end
perform_request(action, data, *args)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 43 def perform_request action, data, *args response = communicate action, data RESPONSE_CLASSES[response[:code]].from_udp(*args, response[:data]) end
process_response(response, transaction_id)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 91 def process_response response, transaction_id check_transaction_id response, transaction_id response_code = extract_response_code response check_response_length response, response_code {code: response_code, data: response[8..-1]} end
scrape_request_data(info_hashes)
click to toggle source
# File lib/torckapi/tracker/udp.rb, line 53 def scrape_request_data info_hashes info_hashes.map { |i| [i].pack('H*') }.join end