Randomized pieces to download

This commit is contained in:
Ben Davis
2017-08-29 12:34:02 +01:00
parent dba46bf8a7
commit 91c8e44d48
9 changed files with 73 additions and 23 deletions
+4
View File
@@ -10,6 +10,7 @@
0434EAB818A3C318E433338A /* Pods_BitTorrentTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8680B0EA21B5A20E03DEE6D /* Pods_BitTorrentTests.framework */; }; 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 */; }; 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 */; }; 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 */; }; B50B24F71F0A553F00C23E7C /* UDPConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50B24F61F0A553B00C23E7C /* UDPConnectionTests.swift */; };
B50B24F91F0A554A00C23E7C /* UDPConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50B24F81F0A554A00C23E7C /* UDPConnection.swift */; }; B50B24F91F0A554A00C23E7C /* UDPConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50B24F81F0A554A00C23E7C /* UDPConnection.swift */; };
B514DD7B1F40971D00C932F8 /* TorrentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B514DD7A1F40971D00C932F8 /* TorrentViewController.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; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; B514DD7A1F40971D00C932F8 /* TorrentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TorrentViewController.swift; sourceTree = "<group>"; };
@@ -407,6 +409,7 @@
B514DDA31F40E96100C932F8 /* CombinedNetworkSpeedTracker.swift */, B514DDA31F40E96100C932F8 /* CombinedNetworkSpeedTracker.swift */,
B514DD8E1F40C53C00C932F8 /* NetworkSpeedTrackerTests.swift */, B514DD8E1F40C53C00C932F8 /* NetworkSpeedTrackerTests.swift */,
B514DD9B1F40DD1B00C932F8 /* URL.swift */, B514DD9B1F40DD1B00C932F8 /* URL.swift */,
B501A5571F557E9E00B87911 /* RandomEnumeration.swift */,
); );
path = Utilities; path = Utilities;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -982,6 +985,7 @@
B558F4831F0A647D00438BB4 /* InternetProtocol.swift in Sources */, B558F4831F0A647D00438BB4 /* InternetProtocol.swift in Sources */,
B527F62B1F1BD5FA001F06AF /* TorrentPieceDownloadBuffer.swift in Sources */, B527F62B1F1BD5FA001F06AF /* TorrentPieceDownloadBuffer.swift in Sources */,
B5BFD9CC1F3FAF9A00CE0186 /* TorrentTrackerManager.swift in Sources */, B5BFD9CC1F3FAF9A00CE0186 /* TorrentTrackerManager.swift in Sources */,
B501A5581F557E9E00B87911 /* RandomEnumeration.swift in Sources */,
B54D0C7A1CA69FAD004343BD /* TorrentMetaInfo.swift in Sources */, B54D0C7A1CA69FAD004343BD /* TorrentMetaInfo.swift in Sources */,
B5C06F131F12CDD8005730B3 /* TorrentPeer.swift in Sources */, B5C06F131F12CDD8005730B3 /* TorrentPeer.swift in Sources */,
B5F81E4B1F04399800B25C70 /* TorrentTrackerResponse.swift in Sources */, B5F81E4B1F04399800B25C70 /* TorrentTrackerResponse.swift in Sources */,
+19 -10
View File
@@ -92,15 +92,24 @@ public struct BitField: Equatable {
} }
} }
extension BitField: Sequence { extension BitField: Collection {
public func makeIterator() -> AnyIterator<(index: Int, isSet: Bool)> {
var index = 0 public typealias Index = Array<Bool>.Index
return AnyIterator {
guard index < self.size else { return nil } public var startIndex: Index {
defer { return value.startIndex
index += 1 }
}
return (index, self.isSet(at: index)) 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) pendingRequests.remove(at: pendingIndex)
} }
} }
@@ -43,7 +43,7 @@ class TorrentProgressManager {
} }
func getNextPieceToDownload(from availablePieces: BitField) -> TorrentPieceRequest? { 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) { if !progress.hasPiece(i) && !progress.isCurrentlyDownloading(piece: i) {
progress.setCurrentlyDownloading(piece: i) progress.setCurrentlyDownloading(piece: i)
return (i, metaInfo.info.lengthOfPiece(at: i), metaInfo.info.pieces[i]) return (i, metaInfo.info.lengthOfPiece(at: i), metaInfo.info.pieces[i])
@@ -12,10 +12,10 @@ import CocoaAsyncSocket
class GCDAsyncSocketStub: GCDAsyncSocket { class GCDAsyncSocketStub: GCDAsyncSocket {
var connectToHostCalled = false var connectToHostCalled = false
var connectToHostParameters: (host: String, port: UInt16)? var connectToHostParameters: (host: String, port: UInt16, timeout: TimeInterval)?
override func connect(toHost host: String, onPort port: UInt16) throws { override func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws {
connectToHostCalled = true connectToHostCalled = true
connectToHostParameters = (host, port) connectToHostParameters = (host, port, timeout)
} }
var readDataCalled = false var readDataCalled = false
@@ -61,7 +61,7 @@ class TCPConnection: NSObject, TCPConnectionProtocol {
} }
func connect(to host: String, onPort port: UInt16) throws { 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() { 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)
}
}
+3 -2
View File
@@ -42,6 +42,7 @@ enum TorrentInfoRowData: Int {
func value(using client: TorrentClient) -> String { func value(using client: TorrentClient) -> String {
let speedSampleSize: TimeInterval = 5 let speedSampleSize: TimeInterval = 5
let etaSampleSize: TimeInterval = 30
switch self { switch self {
@@ -73,8 +74,8 @@ enum TorrentInfoRowData: Int {
return "????" return "????"
case .eta: case .eta:
let speed = client.downloadSpeedTracker.numberOfBytesDownloaded(over: speedSampleSize) let speed = client.downloadSpeedTracker.numberOfBytesDownloaded(over: etaSampleSize)
let speedPerSecond = Double(speed) / speedSampleSize let speedPerSecond = Double(speed) / etaSampleSize
guard speed > 0 else { return "" } guard speed > 0 else { return "" }
let remaining = client.progress.remaining * client.metaInfo.info.pieceLength let remaining = client.progress.remaining * client.metaInfo.info.pieceLength
@@ -92,10 +92,10 @@ extension TorrentViewController: UITableViewDataSource {
return startCell return startCell
} else { } else {
let reCheckCell = UITableViewCell(style: .default, reuseIdentifier: nil) let reCheckCell = UITableViewCell(style: .default, reuseIdentifier: nil)
startCell.textLabel?.text = "Start" reCheckCell.textLabel?.text = "Start"
startCell.textLabel?.textAlignment = .center reCheckCell.textLabel?.textAlignment = .center
startCell.textLabel?.textColor = .blue reCheckCell.textLabel?.textColor = .blue
return startCell return reCheckCell
} }
} }
} }