Randomized pieces to download
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
0434EAB818A3C318E433338A /* Pods_BitTorrentTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8680B0EA21B5A20E03DEE6D /* Pods_BitTorrentTests.framework */; };
|
||||
34D4082D0E0A2C899857DC89 /* Pods_BitTorrent.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B47AE52A67ECE61259FCDAD /* Pods_BitTorrent.framework */; };
|
||||
867491B4C409A91D4D72CCE7 /* Pods_BitTorrent_BitTorrentExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97F9FB9F74204574FF6840B /* Pods_BitTorrent_BitTorrentExample.framework */; };
|
||||
B501A5581F557E9E00B87911 /* RandomEnumeration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501A5571F557E9E00B87911 /* RandomEnumeration.swift */; };
|
||||
B50B24F71F0A553F00C23E7C /* UDPConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50B24F61F0A553B00C23E7C /* UDPConnectionTests.swift */; };
|
||||
B50B24F91F0A554A00C23E7C /* UDPConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50B24F81F0A554A00C23E7C /* UDPConnection.swift */; };
|
||||
B514DD7B1F40971D00C932F8 /* TorrentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B514DD7A1F40971D00C932F8 /* TorrentViewController.swift */; };
|
||||
@@ -168,6 +169,7 @@
|
||||
8B47AE52A67ECE61259FCDAD /* Pods_BitTorrent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BitTorrent.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
99A91AD4708288B297A8B700 /* Pods-BitTorrentTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BitTorrentTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BitTorrentTests/Pods-BitTorrentTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A8680B0EA21B5A20E03DEE6D /* Pods_BitTorrentTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BitTorrentTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B501A5571F557E9E00B87911 /* RandomEnumeration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomEnumeration.swift; sourceTree = "<group>"; };
|
||||
B50B24F61F0A553B00C23E7C /* UDPConnectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPConnectionTests.swift; sourceTree = "<group>"; };
|
||||
B50B24F81F0A554A00C23E7C /* UDPConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPConnection.swift; sourceTree = "<group>"; };
|
||||
B514DD7A1F40971D00C932F8 /* TorrentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TorrentViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -407,6 +409,7 @@
|
||||
B514DDA31F40E96100C932F8 /* CombinedNetworkSpeedTracker.swift */,
|
||||
B514DD8E1F40C53C00C932F8 /* NetworkSpeedTrackerTests.swift */,
|
||||
B514DD9B1F40DD1B00C932F8 /* URL.swift */,
|
||||
B501A5571F557E9E00B87911 /* RandomEnumeration.swift */,
|
||||
);
|
||||
path = Utilities;
|
||||
sourceTree = "<group>";
|
||||
@@ -982,6 +985,7 @@
|
||||
B558F4831F0A647D00438BB4 /* InternetProtocol.swift in Sources */,
|
||||
B527F62B1F1BD5FA001F06AF /* TorrentPieceDownloadBuffer.swift in Sources */,
|
||||
B5BFD9CC1F3FAF9A00CE0186 /* TorrentTrackerManager.swift in Sources */,
|
||||
B501A5581F557E9E00B87911 /* RandomEnumeration.swift in Sources */,
|
||||
B54D0C7A1CA69FAD004343BD /* TorrentMetaInfo.swift in Sources */,
|
||||
B5C06F131F12CDD8005730B3 /* TorrentPeer.swift in Sources */,
|
||||
B5F81E4B1F04399800B25C70 /* TorrentTrackerResponse.swift in Sources */,
|
||||
|
||||
@@ -92,15 +92,24 @@ public struct BitField: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
extension BitField: Sequence {
|
||||
public func makeIterator() -> AnyIterator<(index: Int, isSet: Bool)> {
|
||||
var index = 0
|
||||
return AnyIterator {
|
||||
guard index < self.size else { return nil }
|
||||
defer {
|
||||
index += 1
|
||||
}
|
||||
return (index, self.isSet(at: index))
|
||||
}
|
||||
extension BitField: Collection {
|
||||
|
||||
public typealias Index = Array<Bool>.Index
|
||||
|
||||
public var startIndex: Index {
|
||||
return value.startIndex
|
||||
}
|
||||
|
||||
public var endIndex: Index {
|
||||
return value.endIndex
|
||||
}
|
||||
|
||||
public subscript(position: Index) -> (index: Int, isSet: Bool) {
|
||||
precondition(indices.contains(position), "out of bounds")
|
||||
return (index: position, isSet: value[position])
|
||||
}
|
||||
|
||||
public func index(after i: Index) -> Index {
|
||||
return value.index(after: i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,4 @@ class TorrentPieceDownloadBuffer {
|
||||
|
||||
pendingRequests.remove(at: pendingIndex)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class TorrentProgressManager {
|
||||
}
|
||||
|
||||
func getNextPieceToDownload(from availablePieces: BitField) -> TorrentPieceRequest? {
|
||||
for (i, isSet) in availablePieces where isSet {
|
||||
for (i, isSet) in availablePieces.pseudoRandomized where isSet {
|
||||
if !progress.hasPiece(i) && !progress.isCurrentlyDownloading(piece: i) {
|
||||
progress.setCurrentlyDownloading(piece: i)
|
||||
return (i, metaInfo.info.lengthOfPiece(at: i), metaInfo.info.pieces[i])
|
||||
|
||||
@@ -12,10 +12,10 @@ import CocoaAsyncSocket
|
||||
class GCDAsyncSocketStub: GCDAsyncSocket {
|
||||
|
||||
var connectToHostCalled = false
|
||||
var connectToHostParameters: (host: String, port: UInt16)?
|
||||
override func connect(toHost host: String, onPort port: UInt16) throws {
|
||||
var connectToHostParameters: (host: String, port: UInt16, timeout: TimeInterval)?
|
||||
override func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws {
|
||||
connectToHostCalled = true
|
||||
connectToHostParameters = (host, port)
|
||||
connectToHostParameters = (host, port, timeout)
|
||||
}
|
||||
|
||||
var readDataCalled = false
|
||||
|
||||
@@ -61,7 +61,7 @@ class TCPConnection: NSObject, TCPConnectionProtocol {
|
||||
}
|
||||
|
||||
func connect(to host: String, onPort port: UInt16) throws {
|
||||
try socket.connect(toHost: host, onPort: port)
|
||||
try socket.connect(toHost: host, onPort: port, withTimeout: 15)
|
||||
}
|
||||
|
||||
func disconnect() {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// RandomEnumeration.swift
|
||||
// BitTorrent
|
||||
//
|
||||
// Created by Ben Davis on 29/08/2017.
|
||||
// Copyright © 2017 Ben Davis. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct PseudoRandomizedSequence<Col, Elem>: Sequence
|
||||
where Col: Collection, Col.Element == Elem, Col.Index == Int, Col.IndexDistance == Int {
|
||||
|
||||
fileprivate let orderedSequence: Col
|
||||
|
||||
func makeIterator() -> AnyIterator<Elem> {
|
||||
|
||||
let length = orderedSequence.count
|
||||
let seed = Int(arc4random()) % length
|
||||
let increment = 13 // prime as the step
|
||||
|
||||
var generatedNumber = seed
|
||||
var count = 0
|
||||
|
||||
return AnyIterator {
|
||||
guard count != length else { return nil }
|
||||
count += 1
|
||||
generatedNumber = (generatedNumber + increment) % length
|
||||
return self.orderedSequence[generatedNumber]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Collection where Index == Int, IndexDistance == Int {
|
||||
var pseudoRandomized: PseudoRandomizedSequence<Self, Element> {
|
||||
return PseudoRandomizedSequence(orderedSequence: self)
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ enum TorrentInfoRowData: Int {
|
||||
func value(using client: TorrentClient) -> String {
|
||||
|
||||
let speedSampleSize: TimeInterval = 5
|
||||
let etaSampleSize: TimeInterval = 30
|
||||
|
||||
switch self {
|
||||
|
||||
@@ -73,8 +74,8 @@ enum TorrentInfoRowData: Int {
|
||||
return "????"
|
||||
|
||||
case .eta:
|
||||
let speed = client.downloadSpeedTracker.numberOfBytesDownloaded(over: speedSampleSize)
|
||||
let speedPerSecond = Double(speed) / speedSampleSize
|
||||
let speed = client.downloadSpeedTracker.numberOfBytesDownloaded(over: etaSampleSize)
|
||||
let speedPerSecond = Double(speed) / etaSampleSize
|
||||
guard speed > 0 else { return "∞" }
|
||||
|
||||
let remaining = client.progress.remaining * client.metaInfo.info.pieceLength
|
||||
|
||||
@@ -92,10 +92,10 @@ extension TorrentViewController: UITableViewDataSource {
|
||||
return startCell
|
||||
} else {
|
||||
let reCheckCell = UITableViewCell(style: .default, reuseIdentifier: nil)
|
||||
startCell.textLabel?.text = "Start"
|
||||
startCell.textLabel?.textAlignment = .center
|
||||
startCell.textLabel?.textColor = .blue
|
||||
return startCell
|
||||
reCheckCell.textLabel?.text = "Start"
|
||||
reCheckCell.textLabel?.textAlignment = .center
|
||||
reCheckCell.textLabel?.textColor = .blue
|
||||
return reCheckCell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user