torckapi 0.0.23 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0e78cdf84987163d2164e0eab58654e6c0825c6
4
- data.tar.gz: 7516aecf37f02107ce58f5c193dfd1a9285f7289
3
+ metadata.gz: 128514fdb065b8c1127accfd9d1f34faa850abbb
4
+ data.tar.gz: 9ec91b782fb80a643e27a29b59d23913cbf9c5ab
5
5
  SHA512:
6
- metadata.gz: 3c560a87c520bf0f0220fb8608e72cc0072455aeb7be1ed884d8bbb1bb285eb3e9e3f01a3d500e49ee31c99cdaeab6ed241acb6e8e035fbf9dcfe6cea265a0a6
7
- data.tar.gz: 76931f6d709de866750b102a8097d7fbf2b30dbc098c419d4208cf83a10fd54dc411545cf080b8fcd371446a3653e783abd93ce333671eb180b025337a554e38
6
+ metadata.gz: 11251aa9696786eb80c58cd38e108de956363cceb110120e9b2df4f65cc7628645520088571f4c86aa446cfbc7b7f4f89588482c71841e9217279480a2de4c80
7
+ data.tar.gz: 236b55602c853b01eb0882c0f6852559e9378dedb79c78658c4bc08f57e7004f0647442b947ceb5b7afe24e71c2663837ea09910a72043d6929aeab8e2b85eda
@@ -10,6 +10,7 @@ module Torckapi
10
10
  CommunicationFailedError = Class.new(CommunicationError)
11
11
  CommunicationTimeoutError = Class.new(CommunicationError)
12
12
  MalformedResponseError = Class.new(Error)
13
+ LittleEndianResponseError = Class.new(MalformedResponseError)
13
14
  TransactionIdMismatchError = Class.new(CommunicationError)
14
15
  end
15
16
  end
@@ -30,7 +30,7 @@ module Torckapi
30
30
 
31
31
  def initialize url, options={}
32
32
  @url = url
33
- @options = {timeout: 15, tries: 3}.merge(options)
33
+ @options = {timeout: 15, tries: 7}.merge(options)
34
34
  end
35
35
  end
36
36
  end
@@ -7,13 +7,13 @@ module Torckapi
7
7
  class HTTP < Base
8
8
  # (see Base#announce)
9
9
  def announce info_hash
10
- super info_hash
10
+ super
11
11
  Torckapi::Response::Announce.from_http(info_hash, perform_request(url_for(@url.dup, Announce, info_hash)))
12
12
  end
13
13
 
14
14
  # (see Base#scrape)
15
15
  def scrape info_hashes=[]
16
- super info_hashes
16
+ super
17
17
  Torckapi::Response::Scrape.from_http(perform_request(url_for(@url.dup, Scrape, info_hashes)))
18
18
  end
19
19
 
@@ -22,7 +22,7 @@ module Torckapi
22
22
  REQUEST_ACTIONS = [Announce = 1, Scrape = 2].freeze
23
23
 
24
24
  def initialize url, options={}
25
- super url, options
25
+ super
26
26
  @url.query ||= ""
27
27
  end
28
28
 
@@ -8,12 +8,12 @@ module Torckapi
8
8
  # Implementation of http://www.bittorrent.org/beps/bep_0015.html
9
9
  class UDP < Base
10
10
  def announce info_hash, peer_id=SecureRandom.random_bytes(20)
11
- super info_hash
11
+ super
12
12
  perform_request Announce, announce_request_data(info_hash, peer_id), info_hash
13
13
  end
14
14
 
15
15
  def scrape info_hashes=[]
16
- super info_hashes
16
+ super
17
17
  perform_request Scrape, scrape_request_data(info_hashes), info_hashes
18
18
  end
19
19
 
@@ -23,12 +23,27 @@ module Torckapi
23
23
  REQUEST_ACTIONS = [Connect = 0, Announce = 1, Scrape = 2].freeze
24
24
  RESPONSE_CLASSES = [nil, Torckapi::Response::Announce, Torckapi::Response::Scrape, Torckapi::Response::Error].freeze
25
25
  RESPONSE_MIN_LENGTHS = [16, 20, 8, 8].freeze
26
+ RESPONSE_CODES = 0..RESPONSE_CLASSES.length
27
+
28
+ def initialize url, options={}
29
+ super
30
+ @state = nil
31
+ @connection_id = nil
32
+ @communicated_at = 0
33
+ end
34
+
35
+ def connected?
36
+ @connection_id && @communicated_at.to_i >= Time.now.to_i - CONNECTION_TIMEOUT
37
+ end
38
+
39
+ def connecting?
40
+ @state == :connecting
41
+ end
26
42
 
27
43
  def perform_request action, data, *args
28
- connect
29
44
  response = communicate action, data
30
45
 
31
- RESPONSE_CLASSES[response[:type]].from_udp(*args, response[:data])
46
+ RESPONSE_CLASSES[response[:code]].from_udp(*args, response[:data])
32
47
  end
33
48
 
34
49
  def announce_request_data info_hash, peer_id
@@ -40,29 +55,31 @@ module Torckapi
40
55
  end
41
56
 
42
57
  def connect
43
- return if @connection_id && @communicated_at.to_i >= Time.now.to_i - CONNECTION_TIMEOUT
58
+ return if connected? || connecting?
44
59
 
45
- @connection_id = [0x041727101980].pack('Q>')
60
+ @state, @connection_id = :connecting, [0x041727101980].pack('Q>')
46
61
  response = communicate Connect
47
- @connection_id = response[:data]
62
+ @state, @connection_id = nil, response[:data]
48
63
  end
49
64
 
50
65
  def communicate action, data=nil
51
66
  @socket ||= UDPSocket.new
52
67
 
53
- transaction_id = SecureRandom.random_bytes(4)
54
68
  tries = 0
55
69
  response = nil
56
70
 
57
71
  begin
72
+ timeout = @options[:timeout] * (2 ** tries)
73
+ connect
74
+ transaction_id = SecureRandom.random_bytes(4)
58
75
  packet = [@connection_id, [action].pack('L>'), transaction_id, data].join
59
76
 
60
- Timeout::timeout(@options[:timeout], CommunicationTimeoutError) do
77
+ Timeout::timeout(timeout, CommunicationTimeoutError) do
61
78
  @socket.send(packet, 0, @url.host, @url.port)
62
79
  response = parse_response @socket.recvfrom(65536), transaction_id
63
80
  @communicated_at = Time.now
64
81
  end
65
- rescue CommunicationTimeoutError
82
+ rescue CommunicationTimeoutError, LittleEndianResponseError => e
66
83
  retry if (tries += 1) <= @options[:tries]
67
84
  end
68
85
 
@@ -72,14 +89,18 @@ module Torckapi
72
89
  end
73
90
 
74
91
  def parse_response data, transaction_id
75
- response, sender_addrinfo = data
76
-
77
- response_type = response[0..3].unpack('L>')[0]
92
+ response = data[0]
78
93
 
79
94
  raise TransactionIdMismatchError, response.inspect if transaction_id != response[4..7]
80
- raise MalformedResponseError, response.inspect if RESPONSE_MIN_LENGTHS[response_type] > response.length
81
95
 
82
- {type: response_type, data: response[8..-1]}
96
+ response_code, response_code_le = response[0..3].unpack('L>')[0], response[0..3].unpack('L<')[0]
97
+
98
+ unless RESPONSE_CODES.include?(response_code)
99
+ raise (RESPONSE_CODES.include?(response_code_le) ? LittleEndianResponseError : MalformedResponseError), response.inspect
100
+ end
101
+ raise MalformedResponseError, response.inspect if RESPONSE_MIN_LENGTHS[response_code] > response.length
102
+
103
+ {code: response_code, data: response[8..-1]}
83
104
  end
84
105
  end
85
106
  end
@@ -1,3 +1,3 @@
1
1
  module Torckapi
2
- VERSION = "0.0.23"
2
+ VERSION = "0.0.24"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: torckapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.23
4
+ version: 0.0.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Krupenik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-24 00:00:00.000000000 Z
11
+ date: 2014-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake