quartz_torrent 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -90,6 +90,20 @@ module QuartzTorrent
90
90
  raise "Malformed size '#{size}'"
91
91
  end
92
92
  end
93
- end
94
93
 
94
+ # Parse a duration of time into seconds.
95
+ def self.parseTime(time)
96
+ return nil if ! time
97
+
98
+ if time =~ /(?:(\d+)\s*h)?\s*(?:(\d+)\s*m)?\s*(?:(\d+)\s*s)?/
99
+ h = $1.to_i
100
+ m = $2.to_i
101
+ s = $3.to_i
102
+
103
+ h*3600+m*60+s
104
+ else
105
+ raise "Malformed duration '#{time}'"
106
+ end
107
+ end
108
+ end
95
109
  end
@@ -55,6 +55,8 @@ module QuartzTorrent
55
55
  @downRateLimit = nil
56
56
  @upRateLimit = nil
57
57
  @ratio = nil
58
+ @uploadDuration = nil
59
+ @downloadCompletedTime = nil
58
60
  end
59
61
  # The torrents Metainfo.Info struct. This is nil if the torrent has no metadata and we need to download it
60
62
  # (i.e. a magnet link)
@@ -99,6 +101,11 @@ module QuartzTorrent
99
101
  # After we have completed downloading a torrent, we will continue to upload until we have
100
102
  # uploaded ratio * torrent_size bytes. If nil, no limit on upload.
101
103
  attr_accessor :ratio
104
+ # Maximum amount of time in seconds that the torrent can be in the uploading state before it's paused.
105
+ attr_accessor :uploadDuration
106
+ # Time at which we completely downloaded all bytes of the torrent.
107
+ attr_accessor :downloadCompletedTime
108
+
102
109
  end
103
110
 
104
111
  # Data about torrents for use by the end user.
@@ -146,6 +153,7 @@ module QuartzTorrent
146
153
  # After we have completed downloading a torrent, we will continue to upload until we have
147
154
  # uploaded ratio * torrent_size bytes. If nil, no limit on upload.
148
155
  attr_accessor :ratio
156
+ attr_accessor :uploadDuration
149
157
  attr_accessor :bytesUploadedDataOnly
150
158
  attr_accessor :bytesDownloadedDataOnly
151
159
  attr_accessor :bytesUploaded
@@ -210,6 +218,7 @@ module QuartzTorrent
210
218
  @downloadRateLimit = torrentData.downRateLimit.unitsPerSecond if torrentData.downRateLimit
211
219
  @uploadRateLimit = torrentData.upRateLimit.unitsPerSecond if torrentData.upRateLimit
212
220
  @ratio = torrentData.ratio
221
+ @uploadDuration = torrentData.uploadDuration
213
222
  end
214
223
 
215
224
  def buildPeersList(torrentData)
@@ -360,6 +369,18 @@ module QuartzTorrent
360
369
  torrentData.ratio = ratio
361
370
  end
362
371
 
372
+ # Set the maximum amount of time (in seconds) that a torrent can be in the upload-only state before
373
+ # it is paused. Pass nil to disable.
374
+ def setUploadDuration(infoHash, seconds)
375
+ torrentData = @torrentData[infoHash]
376
+ if ! torrentData
377
+ @logger.warn "Asked to set upload duration for a non-existent torrent #{QuartzTorrent.bytesToHex(infoHash)}"
378
+ return
379
+ end
380
+
381
+ torrentData.uploadDuration = seconds
382
+ end
383
+
363
384
  # Reactor method called when a peer has connected to us.
364
385
  def serverInit(metadata, addr, port)
365
386
  # A peer connected to us
@@ -825,11 +846,20 @@ module QuartzTorrent
825
846
  return
826
847
  end
827
848
 
828
- if torrentData.state == :uploading && (torrentData.state != :paused) && torrentData.ratio
829
- if torrentData.bytesUploadedDataOnly >= torrentData.ratio*torrentData.blockState.totalLength
830
- @logger.info "Pausing torrent due to upload ratio limit." if torrentData.metainfoPieceState.complete?
831
- setPaused(infoHash, true)
832
- return
849
+ if torrentData.state == :uploading && (torrentData.state != :paused)
850
+ if torrentData.ratio
851
+ if torrentData.bytesUploadedDataOnly >= torrentData.ratio*torrentData.blockState.totalLength
852
+ @logger.info "Pausing torrent due to upload ratio limit." if torrentData.metainfoPieceState.complete?
853
+ setPaused(infoHash, true)
854
+ return
855
+ end
856
+ end
857
+ if torrentData.uploadDuration && torrentData.downloadCompletedTime
858
+ if Time.new > torrentData.downloadCompletedTime + torrentData.uploadDuration
859
+ @logger.info "Pausing torrent due to upload duration being reached." if torrentData.metainfoPieceState.complete?
860
+ setPaused(infoHash, true)
861
+ return
862
+ end
833
863
  end
834
864
  end
835
865
 
@@ -887,9 +917,10 @@ module QuartzTorrent
887
917
  end
888
918
 
889
919
  if blockInfos.size == 0
890
- if torrentData.blockState.completePieceBitfield.allSet?
920
+ if torrentData.state != :uploading && torrentData.blockState.completePieceBitfield.allSet?
891
921
  @logger.info "Download of #{QuartzTorrent.bytesToHex(infoHash)} complete."
892
922
  torrentData.state = :uploading
923
+ torrentData.downloadCompletedTime = Time.new
893
924
  end
894
925
  end
895
926
 
@@ -1036,7 +1067,11 @@ module QuartzTorrent
1036
1067
  end
1037
1068
 
1038
1069
  peer.bitfield = msg.bitfield
1039
- peer.bitfield.length = torrentData.info.pieces.length
1070
+ if torrentData.info
1071
+ peer.bitfield.length = torrentData.info.pieces.length
1072
+ else
1073
+ @logger.warn "A peer connected and sent a bitfield but we don't know the length of the torrent yet. Assuming number of pieces is divisible by 8"
1074
+ end
1040
1075
 
1041
1076
  if ! torrentData.blockState
1042
1077
  @logger.warn "Bitfield: no blockstate yet."
@@ -1612,6 +1647,13 @@ module QuartzTorrent
1612
1647
  @handler.setUploadRatio(infoHash, ratio)
1613
1648
  end
1614
1649
 
1650
+ # Set the maximum amount of time (in seconds) that a torrent can be in the upload-only state before
1651
+ # it is paused. Pass nil to disable.
1652
+ def setUploadDuration(infoHash, seconds)
1653
+ raise "upload ratio must be Numeric, not a #{seconds.class}" if seconds && ! seconds.is_a?(Numeric)
1654
+ @handler.setUploadDuration(infoHash, seconds)
1655
+ end
1656
+
1615
1657
  # Remove a currently running torrent
1616
1658
  def removeTorrent(infoHash, deleteFiles = false)
1617
1659
  @handler.removeTorrent(infoHash, deleteFiles)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quartz_torrent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: