mirror of
https://github.com/asamy/ctorrent
synced 2025-10-05 23:52:41 +02:00
fix bitset::count() bug and improvements
Signed-off-by: Ahmed Samy <f.fallen45@gmail.com>
This commit is contained in:
4
Makefile
4
Makefile
@@ -13,9 +13,9 @@ DEP_DIR = dep
|
|||||||
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
|
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
|
||||||
|
|
||||||
CXX = $(CROSS_BUILD)g++
|
CXX = $(CROSS_BUILD)g++
|
||||||
BTYPE = -O3
|
BTYPE = -O0 -g
|
||||||
CXXFLAGS = -std=c++0x $(DEPFLAGS) $(BTYPE) -fopenmp \
|
CXXFLAGS = -std=c++0x $(DEPFLAGS) $(BTYPE) -fopenmp \
|
||||||
-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -I"."
|
-Wall -Wextra -Werror -Wno-unused-variable -Wno-unused-parameter -I"."
|
||||||
|
|
||||||
LIBS += -fopenmp -lboost_system -lboost_filesystem -lboost_program_options
|
LIBS += -fopenmp -lboost_system -lboost_filesystem -lboost_program_options
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@@ -99,7 +99,7 @@ VectorType Bencode::readVector()
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
case 'i': ret.push_back(readInt()); break;
|
case 'i': ret.push_back(readUint()); break;
|
||||||
case 'l': ret.push_back(readVector()); break;
|
case 'l': ret.push_back(readVector()); break;
|
||||||
case 'd': ret.push_back(readDictionary()); break;
|
case 'd': ret.push_back(readDictionary()); break;
|
||||||
case 'e': return ret;
|
case 'e': return ret;
|
||||||
@@ -143,7 +143,7 @@ Dictionary Bencode::readDictionary()
|
|||||||
return Dictionary();
|
return Dictionary();
|
||||||
|
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
case 'i': ret[key] = readInt(); break;
|
case 'i': ret[key] = readUint(); break;
|
||||||
case 'l': ret[key] = readVector(); break;
|
case 'l': ret[key] = readVector(); break;
|
||||||
case 'd': ret[key] = readDictionary(); break;
|
case 'd': ret[key] = readDictionary(); break;
|
||||||
default:
|
default:
|
||||||
|
@@ -97,7 +97,7 @@ void Peer::verify()
|
|||||||
m_peerId = peerId;
|
m_peerId = peerId;
|
||||||
m_conn->write(m_handshake, 68);
|
m_conn->write(m_handshake, 68);
|
||||||
m_torrent->handleNewPeer(shared_from_this());
|
m_torrent->handleNewPeer(shared_from_this());
|
||||||
m_eventId = g_sched.addEvent(std::bind(&Peer::sendKeepAlive, shared_from_this()), KEEPALIVE_INTERVAL);
|
// m_eventId = g_sched.addEvent(std::bind(&Peer::sendKeepAlive, shared_from_this()), KEEPALIVE_INTERVAL);
|
||||||
m_conn->read(4, std::bind(&Peer::handle, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
|
m_conn->read(4, std::bind(&Peer::handle, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ void Peer::handleMessage(MessageType messageType, InputMessage in)
|
|||||||
return handleError("received too big piece block of size " + bytesToHumanReadable(payloadSize, true));
|
return handleError("received too big piece block of size " + bytesToHumanReadable(payloadSize, true));
|
||||||
|
|
||||||
auto it = std::find_if(m_queue.begin(), m_queue.end(),
|
auto it = std::find_if(m_queue.begin(), m_queue.end(),
|
||||||
[index](const Piece *piece) { return piece->index == index; });
|
[index](const Piece *piece) { return piece->index == index; });
|
||||||
if (it == m_queue.end())
|
if (it == m_queue.end())
|
||||||
return handleError("received piece " + std::to_string(index) + " which we did not ask for");
|
return handleError("received piece " + std::to_string(index) + " which we did not ask for");
|
||||||
|
|
||||||
@@ -240,17 +240,11 @@ void Peer::handleMessage(MessageType messageType, InputMessage in)
|
|||||||
m_queue.erase(it);
|
m_queue.erase(it);
|
||||||
delete piece;
|
delete piece;
|
||||||
} else {
|
} else {
|
||||||
PieceBlock *block = &piece->blocks[blockIndex];
|
|
||||||
uint8_t *payload = in.getBuffer(payloadSize);
|
uint8_t *payload = in.getBuffer(payloadSize);
|
||||||
if (block->rpos != 0) {
|
PieceBlock *block = &piece->blocks[blockIndex];
|
||||||
memcpy(block->data, payload, std::max(payloadSize, block->size - block->rpos));
|
block->size = payloadSize;
|
||||||
free(payload);
|
block->data = payload;
|
||||||
block->rpos += payloadSize;
|
++piece->currentBlocks;
|
||||||
} else {
|
|
||||||
block->size = block->rpos = payloadSize;
|
|
||||||
block->data = payload;
|
|
||||||
++piece->currentBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (piece->currentBlocks == piece->numBlocks) {
|
if (piece->currentBlocks == piece->numBlocks) {
|
||||||
DataBuffer<uint8_t> pieceData;
|
DataBuffer<uint8_t> pieceData;
|
||||||
@@ -311,7 +305,7 @@ void Peer::handlePieceBlockData(size_t index, size_t begin, const uint8_t *block
|
|||||||
{
|
{
|
||||||
// Check if piece block cancel was issued
|
// Check if piece block cancel was issued
|
||||||
auto it = std::find_if(m_requestedBlocks.begin(), m_requestedBlocks.end(),
|
auto it = std::find_if(m_requestedBlocks.begin(), m_requestedBlocks.end(),
|
||||||
[=] (const PieceBlockInfo &i) { return i.index == index && i.begin == begin; } );
|
[=] (const PieceBlockInfo &i) { return i.index == index && i.begin == begin; } );
|
||||||
if (it == m_requestedBlocks.end())
|
if (it == m_requestedBlocks.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -66,11 +66,7 @@ public:
|
|||||||
void connect(const std::string &ip, const std::string &port);
|
void connect(const std::string &ip, const std::string &port);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Process piece blocks requested, send keepalive, etc.
|
|
||||||
void process();
|
|
||||||
// Used only in server verification (e.g. peer connected to us)
|
|
||||||
void verify();
|
void verify();
|
||||||
|
|
||||||
void handle(const uint8_t *data, size_t size);
|
void handle(const uint8_t *data, size_t size);
|
||||||
void handleMessage(MessageType mType, InputMessage in);
|
void handleMessage(MessageType mType, InputMessage in);
|
||||||
void handleError(const std::string &errmsg);
|
void handleError(const std::string &errmsg);
|
||||||
@@ -100,10 +96,9 @@ protected:
|
|||||||
private:
|
private:
|
||||||
struct PieceBlock {
|
struct PieceBlock {
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t rpos;
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
|
|
||||||
PieceBlock() { data = nullptr; size = rpos = 0; }
|
PieceBlock() { data = nullptr; size = 0; }
|
||||||
~PieceBlock() { delete []data; }
|
~PieceBlock() { delete []data; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -30,6 +30,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
extern std::ofstream logfile;
|
||||||
|
|
||||||
Torrent::Torrent()
|
Torrent::Torrent()
|
||||||
: m_listener(nullptr),
|
: m_listener(nullptr),
|
||||||
@@ -159,12 +162,10 @@ bool Torrent::checkTrackers()
|
|||||||
bool Torrent::nextConnection()
|
bool Torrent::nextConnection()
|
||||||
{
|
{
|
||||||
if (m_listener) {
|
if (m_listener) {
|
||||||
m_listener->accept(
|
m_listener->accept([this] (const ConnectionPtr &c) {
|
||||||
[this] (const ConnectionPtr &c) {
|
auto peer = std::make_shared<Peer>(c, this);
|
||||||
auto peer = std::make_shared<Peer>(c, this);
|
peer->verify();
|
||||||
peer->verify();
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -175,7 +176,7 @@ bool Torrent::nextConnection()
|
|||||||
bool Torrent::queryTrackers(const TrackerQuery &query, uint16_t port)
|
bool Torrent::queryTrackers(const TrackerQuery &query, uint16_t port)
|
||||||
{
|
{
|
||||||
bool success = queryTracker(m_meta.tracker(), query, port);
|
bool success = queryTracker(m_meta.tracker(), query, port);
|
||||||
if (m_meta.trackers().empty())
|
if (success)
|
||||||
return success;
|
return success;
|
||||||
|
|
||||||
for (const boost::any &s : m_meta.trackers()) {
|
for (const boost::any &s : m_meta.trackers()) {
|
||||||
@@ -186,10 +187,10 @@ bool Torrent::queryTrackers(const TrackerQuery &query, uint16_t port)
|
|||||||
return true;
|
return true;
|
||||||
} else if (s.type() == typeid(std::string) &&
|
} else if (s.type() == typeid(std::string) &&
|
||||||
queryTracker(Bencode::cast<std::string>(&s), query, port))
|
queryTracker(Bencode::cast<std::string>(&s), query, port))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Torrent::queryTracker(const std::string &furl, const TrackerQuery &q, uint16_t tport)
|
bool Torrent::queryTracker(const std::string &furl, const TrackerQuery &q, uint16_t tport)
|
||||||
@@ -293,6 +294,7 @@ void Torrent::addPeer(const PeerPtr &peer)
|
|||||||
if (it != m_blacklisted.end())
|
if (it != m_blacklisted.end())
|
||||||
m_blacklisted.erase(it);
|
m_blacklisted.erase(it);
|
||||||
|
|
||||||
|
logfile << peer->getIP() << ": now connected" << std::endl;
|
||||||
m_peers.insert(std::make_pair(peer->ip(), peer));
|
m_peers.insert(std::make_pair(peer->ip(), peer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +303,8 @@ void Torrent::removePeer(const PeerPtr &peer, const std::string &errmsg)
|
|||||||
auto it = m_peers.find(peer->ip());
|
auto it = m_peers.find(peer->ip());
|
||||||
if (it != m_peers.end())
|
if (it != m_peers.end())
|
||||||
m_peers.erase(it);
|
m_peers.erase(it);
|
||||||
|
|
||||||
|
logfile << peer->getIP() << ": closing: " << errmsg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Torrent::disconnectPeers()
|
void Torrent::disconnectPeers()
|
||||||
@@ -325,51 +329,58 @@ void Torrent::sendBitfield(const PeerPtr &peer)
|
|||||||
|
|
||||||
void Torrent::requestPiece(const PeerPtr &peer)
|
void Torrent::requestPiece(const PeerPtr &peer)
|
||||||
{
|
{
|
||||||
size_t index = m_fileManager.getPieceforRequest([peer] (size_t i) { return peer->hasPiece(i); });
|
size_t index = m_fileManager.getPieceforRequest(std::bind(&Peer::hasPiece, peer, std::placeholders::_1));
|
||||||
if (index != std::numeric_limits<size_t>::max())
|
if (index != std::numeric_limits<size_t>::max())
|
||||||
peer->sendPieceRequest(index);
|
peer->sendPieceRequest(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Torrent::handlePieceCompleted(const PeerPtr &peer, uint32_t index, DataBuffer<uint8_t> &&data)
|
bool Torrent::handlePieceCompleted(const PeerPtr &peer, uint32_t index, DataBuffer<uint8_t> &&data)
|
||||||
{
|
{
|
||||||
uint32_t downloaded = data.size();
|
logfile << peer->getIP() << ": finished downloading piece: " << index << std::endl;
|
||||||
if (m_fileManager.writePieceBlock(index, peer->ip(), std::move(data))) {
|
if (m_fileManager.writePieceBlock(index, peer->ip(), std::move(data)))
|
||||||
m_downloadedBytes += downloaded;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
m_wastedBytes += downloaded;
|
m_wastedBytes += data.size();
|
||||||
++m_hashMisses;
|
++m_hashMisses;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Torrent::handleRequestBlock(const PeerPtr &peer, uint32_t index, uint32_t begin, uint32_t length)
|
bool Torrent::handleRequestBlock(const PeerPtr &peer, uint32_t index, uint32_t begin, uint32_t length)
|
||||||
{
|
{
|
||||||
|
logfile << peer->getIP() << ": Requested piece block: " << index << std::endl;
|
||||||
return m_fileManager.requestPieceBlock(index, peer->ip(), begin, length);
|
return m_fileManager.requestPieceBlock(index, peer->ip(), begin, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Torrent::onPieceWriteComplete(uint32_t from, uint32_t index)
|
void Torrent::onPieceWriteComplete(uint32_t from, size_t index)
|
||||||
{
|
{
|
||||||
|
logfile << ip2str(from) << ": Finished writing piece: " << index << std::endl;
|
||||||
|
logfile << "Pieces so far: " << m_fileManager.completedPieces() << "/" << m_fileManager.totalPieces() << std::endl;
|
||||||
|
|
||||||
|
m_downloadedBytes += m_fileManager.pieceSize(index);
|
||||||
for (const auto &it : m_peers)
|
for (const auto &it : m_peers)
|
||||||
if (!it.second->hasPiece(index))
|
if (it.second->ip() != from && !it.second->hasPiece(index))
|
||||||
it.second->sendHave(index);
|
it.second->sendHave(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Torrent::onPieceReadComplete(uint32_t from, uint32_t index, uint32_t begin, uint8_t *block, size_t size)
|
void Torrent::onPieceReadComplete(uint32_t from, size_t index, int64_t begin, uint8_t *block, size_t size)
|
||||||
{
|
{
|
||||||
auto it = m_peers.find(from);
|
auto it = m_peers.find(from);
|
||||||
if (it != m_peers.end()) {
|
if (it != m_peers.end()) {
|
||||||
it->second->sendPieceBlock(index, begin, block, size);
|
it->second->sendPieceBlock(index, begin, block, size);
|
||||||
m_uploadedBytes += size;
|
m_uploadedBytes += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete []block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Torrent::handleTrackerError(Tracker *tracker, const std::string &error)
|
void Torrent::handleTrackerError(Tracker *tracker, const std::string &error)
|
||||||
{
|
{
|
||||||
|
logfile << tracker->host() << ": (T): " << error << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Torrent::handlePeerDebug(const PeerPtr &peer, const std::string &msg)
|
void Torrent::handlePeerDebug(const PeerPtr &peer, const std::string &msg)
|
||||||
{
|
{
|
||||||
|
logfile << peer->getIP() << ": " << msg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Torrent::handleNewPeer(const PeerPtr &peer)
|
void Torrent::handleNewPeer(const PeerPtr &peer)
|
||||||
|
@@ -76,10 +76,10 @@ public:
|
|||||||
clock_t elapsed();
|
clock_t elapsed();
|
||||||
|
|
||||||
// Get associated meta info for this torrent
|
// Get associated meta info for this torrent
|
||||||
const TorrentMeta *meta() const { return &m_meta; }
|
TorrentMeta *meta() { return &m_meta; }
|
||||||
|
|
||||||
// Get associated file manager for this torrent
|
// Get associated file manager for this torrent
|
||||||
const TorrentFileManager *fileManager() const { return &m_fileManager; }
|
TorrentFileManager *fileManager() { return &m_fileManager; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool queryTrackers(const TrackerQuery &r, uint16_t port);
|
bool queryTrackers(const TrackerQuery &r, uint16_t port);
|
||||||
@@ -108,8 +108,8 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// TorrentFileManager -> Torrent
|
// TorrentFileManager -> Torrent
|
||||||
void onPieceWriteComplete(uint32_t from, uint32_t index);
|
void onPieceWriteComplete(uint32_t from, size_t index);
|
||||||
void onPieceReadComplete(uint32_t from, uint32_t index, uint32_t begin, uint8_t *block, size_t size);
|
void onPieceReadComplete(uint32_t from, size_t index, int64_t begin, uint8_t *block, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Server *m_listener;
|
Server *m_listener;
|
||||||
|
@@ -44,8 +44,8 @@ struct ReadRequest {
|
|||||||
size_t index;
|
size_t index;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t from;
|
uint32_t from;
|
||||||
int64_t begin;
|
size_t begin;
|
||||||
int64_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
struct LeastReadRequest {
|
struct LeastReadRequest {
|
||||||
bool operator() (const ReadRequest &lhs, const ReadRequest &rhs) const {
|
bool operator() (const ReadRequest &lhs, const ReadRequest &rhs) const {
|
||||||
@@ -89,21 +89,26 @@ public:
|
|||||||
void unlock_and_notify() { m_mutex.unlock(); m_condition.notify_all(); }
|
void unlock_and_notify() { m_mutex.unlock(); m_condition.notify_all(); }
|
||||||
|
|
||||||
void push_read(const ReadRequest &r) { m_readRequests.push(r); }
|
void push_read(const ReadRequest &r) { m_readRequests.push(r); }
|
||||||
void push_write(WriteRequest &&w) { m_writeRequests.push(std::move(w)); }
|
void push_write(WriteRequest &&w) { m_writeRequests.push(std::move(w)); m_pendingBits.set(w.index); }
|
||||||
void push_file(const TorrentFile &f) { m_files.push_back(f); }
|
void push_file(const TorrentFile &f) { m_files.push_back(f); }
|
||||||
void scan_file(const TorrentFile &f);
|
void scan_file(const TorrentFile &f);
|
||||||
void scan_pieces();
|
void scan_pieces();
|
||||||
|
|
||||||
const bitset *completed_bits() const { return &m_completedBits; }
|
const bitset *completed_bits() const { return &m_completedBits; }
|
||||||
|
size_t pending() const { return m_pendingBits.count(); }
|
||||||
size_t completed_pieces() const { return m_completedBits.count(); }
|
size_t completed_pieces() const { return m_completedBits.count(); }
|
||||||
size_t total_pieces() const { return m_pieces.size(); }
|
size_t total_pieces() const { return m_pieces.size(); }
|
||||||
size_t get_next_piece(const std::function<bool (size_t)> &fun);
|
size_t get_next_piece(const std::function<bool (size_t)> &fun);
|
||||||
size_t compute_downloaded();
|
size_t compute_downloaded();
|
||||||
|
|
||||||
bool piece_done(size_t index) const { return index < m_pieces.size() && m_completedBits.test(index); }
|
bool piece_done(size_t index) const { return index < m_pieces.size() && m_completedBits.test(index); }
|
||||||
|
bool piece_pending(size_t index) const { return index < m_pieces.size() && m_pendingBits.test(index); }
|
||||||
bool intact(size_t index) const { return index < m_pieces.size(); }
|
bool intact(size_t index) const { return index < m_pieces.size(); }
|
||||||
bool is_read_eligible(size_t index, int64_t end) const { return m_completedBits.test(index) && end < piece_length(index); }
|
bool is_read_eligible(size_t index, int64_t end) const { return m_completedBits.test(index) && end < piece_length(index); }
|
||||||
bool is_write_eligible(size_t index, const uint8_t *data, size_t size) const {
|
bool is_write_eligible(size_t index, const uint8_t *data, size_t size) const {
|
||||||
|
if (m_pendingBits.test(index))
|
||||||
|
return false;
|
||||||
|
|
||||||
boost::uuids::detail::sha1 sha1;
|
boost::uuids::detail::sha1 sha1;
|
||||||
sha1.process_bytes(data, size);
|
sha1.process_bytes(data, size);
|
||||||
|
|
||||||
@@ -133,6 +138,7 @@ public:
|
|||||||
auto sha1sums = m_torrent->meta()->sha1sums();
|
auto sha1sums = m_torrent->meta()->sha1sums();
|
||||||
m_pieces.reserve(sha1sums.size());
|
m_pieces.reserve(sha1sums.size());
|
||||||
m_completedBits.construct(sha1sums.size());
|
m_completedBits.construct(sha1sums.size());
|
||||||
|
m_pendingBits.construct(sha1sums.size());
|
||||||
|
|
||||||
for (sha1sum s : sha1sums)
|
for (sha1sum s : sha1sums)
|
||||||
m_pieces.push_back(Piece(s));
|
m_pieces.push_back(Piece(s));
|
||||||
@@ -149,6 +155,8 @@ private:
|
|||||||
std::queue<WriteRequest> m_writeRequests;
|
std::queue<WriteRequest> m_writeRequests;
|
||||||
|
|
||||||
bitset m_completedBits;
|
bitset m_completedBits;
|
||||||
|
bitset m_pendingBits;
|
||||||
|
|
||||||
std::vector<TorrentFile> m_files;
|
std::vector<TorrentFile> m_files;
|
||||||
std::vector<Piece> m_pieces;
|
std::vector<Piece> m_pieces;
|
||||||
|
|
||||||
@@ -165,11 +173,11 @@ void TorrentFileManagerImpl::scan_file(const TorrentFile &f)
|
|||||||
{
|
{
|
||||||
FILE *fp = f.fp;
|
FILE *fp = f.fp;
|
||||||
fseek(fp, 0L, SEEK_END);
|
fseek(fp, 0L, SEEK_END);
|
||||||
off64_t fileLength = ftello64(fp);
|
size_t fileLength = ftello64(fp);
|
||||||
fseek(fp, 0L, SEEK_SET);
|
fseek(fp, 0L, SEEK_SET);
|
||||||
|
|
||||||
if (f.info.length > fileLength) {
|
if (f.info.length > fileLength) {
|
||||||
// truncate(f.info.path.c_str(), f.info.length);
|
truncate(f.info.path.c_str(), f.info.length);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,14 +275,18 @@ void TorrentFileManagerImpl::thread()
|
|||||||
// mark the piece as fully have before we fully wrote it to disk.
|
// mark the piece as fully have before we fully wrote it to disk.
|
||||||
while (!m_writeRequests.empty() && !m_stopped) {
|
while (!m_writeRequests.empty() && !m_stopped) {
|
||||||
const WriteRequest &w = m_writeRequests.front();
|
const WriteRequest &w = m_writeRequests.front();
|
||||||
if (process_write(w))
|
if (!process_write(w))
|
||||||
m_writeRequests.pop();
|
break;
|
||||||
|
|
||||||
|
m_writeRequests.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!m_readRequests.empty() && !m_stopped) {
|
while (!m_readRequests.empty() && !m_stopped) {
|
||||||
ReadRequest r = m_readRequests.top();
|
ReadRequest r = m_readRequests.top();
|
||||||
if (process_read(r))
|
if (!process_read(r))
|
||||||
m_readRequests.pop();
|
break;
|
||||||
|
|
||||||
|
m_readRequests.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@@ -286,16 +298,16 @@ bool TorrentFileManagerImpl::process_read(const ReadRequest &r)
|
|||||||
const TorrentMeta *meta = m_torrent->meta();
|
const TorrentMeta *meta = m_torrent->meta();
|
||||||
int64_t blockBegin = r.begin + r.index * meta->pieceLength();
|
int64_t blockBegin = r.begin + r.index * meta->pieceLength();
|
||||||
int64_t blockEnd = r.begin + r.size;
|
int64_t blockEnd = r.begin + r.size;
|
||||||
uint8_t block[r.size];
|
uint8_t *block = new uint8_t[r.size];
|
||||||
|
|
||||||
int64_t writePos = 0;
|
size_t writePos = 0;
|
||||||
for (const TorrentFile &f : m_files) {
|
for (const TorrentFile &f : m_files) {
|
||||||
int64_t filePos = blockBegin + writePos;
|
|
||||||
const TorrentFileInfo &i = f.info;
|
const TorrentFileInfo &i = f.info;
|
||||||
|
size_t filePos = blockBegin + writePos;
|
||||||
if (filePos < i.begin)
|
if (filePos < i.begin)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int64_t fileEnd = i.begin + i.length;
|
size_t fileEnd = i.begin + i.length;
|
||||||
if (filePos > fileEnd)
|
if (filePos > fileEnd)
|
||||||
continue;
|
continue;
|
||||||
fseek(f.fp, filePos - i.begin, SEEK_SET);
|
fseek(f.fp, filePos - i.begin, SEEK_SET);
|
||||||
@@ -311,15 +323,14 @@ bool TorrentFileManagerImpl::process_read(const ReadRequest &r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: schedule this as well, make sure "block" will live for the period
|
g_sched.addEvent(std::bind(&Torrent::onPieceReadComplete, m_torrent, r.from, r.index, r.begin, block, r.size), 0);
|
||||||
m_torrent->onPieceReadComplete(r.from, r.index, r.begin, block, r.size);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentFileManagerImpl::process_write(const WriteRequest &w)
|
bool TorrentFileManagerImpl::process_write(const WriteRequest &w)
|
||||||
{
|
{
|
||||||
const TorrentMeta *meta = m_torrent->meta();
|
const TorrentMeta *meta = m_torrent->meta();
|
||||||
int64_t beginPos = w.index * meta->pieceLength();
|
size_t beginPos = w.index * meta->pieceLength();
|
||||||
|
|
||||||
const uint8_t *buf = &w.data[0];
|
const uint8_t *buf = &w.data[0];
|
||||||
size_t length = w.data.size();
|
size_t length = w.data.size();
|
||||||
@@ -330,11 +341,11 @@ bool TorrentFileManagerImpl::process_write(const WriteRequest &w)
|
|||||||
if (beginPos < i.begin)
|
if (beginPos < i.begin)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int64_t fileEnd = i.begin + i.length;
|
size_t fileEnd = i.begin + i.length;
|
||||||
if (beginPos >= fileEnd)
|
if (beginPos >= fileEnd)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int64_t amount = fileEnd - beginPos;
|
size_t amount = fileEnd - beginPos;
|
||||||
if (amount > length)
|
if (amount > length)
|
||||||
amount = length;
|
amount = length;
|
||||||
|
|
||||||
@@ -345,6 +356,7 @@ bool TorrentFileManagerImpl::process_write(const WriteRequest &w)
|
|||||||
length -= wrote;
|
length -= wrote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_pendingBits.clear(w.index);
|
||||||
m_completedBits.set(w.index);
|
m_completedBits.set(w.index);
|
||||||
g_sched.addEvent(std::bind(&Torrent::onPieceWriteComplete, m_torrent, w.from, w.index), 0);
|
g_sched.addEvent(std::bind(&Torrent::onPieceWriteComplete, m_torrent, w.from, w.index), 0);
|
||||||
return true;
|
return true;
|
||||||
@@ -358,7 +370,7 @@ size_t TorrentFileManagerImpl::get_next_piece(const std::function<bool (size_t)>
|
|||||||
std::lock_guard<std::mutex> guard(m_mutex);
|
std::lock_guard<std::mutex> guard(m_mutex);
|
||||||
for (size_t i = 0; i < m_pieces.size(); ++i) {
|
for (size_t i = 0; i < m_pieces.size(); ++i) {
|
||||||
Piece *p = &m_pieces[i];
|
Piece *p = &m_pieces[i];
|
||||||
if (m_completedBits.test(i) || !fun(i))
|
if (m_completedBits.test(i) || m_pendingBits.test(i) || !fun(i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!p->pri) {
|
if (!p->pri) {
|
||||||
@@ -437,11 +449,21 @@ size_t TorrentFileManager::computeDownloaded()
|
|||||||
return i->compute_downloaded();
|
return i->compute_downloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t TorrentFileManager::pending() const
|
||||||
|
{
|
||||||
|
return i->pending();
|
||||||
|
}
|
||||||
|
|
||||||
bool TorrentFileManager::pieceDone(size_t index) const
|
bool TorrentFileManager::pieceDone(size_t index) const
|
||||||
{
|
{
|
||||||
return i->piece_done(index);
|
return i->piece_done(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TorrentFileManager::piecePending(size_t index) const
|
||||||
|
{
|
||||||
|
return i->piece_pending(index);
|
||||||
|
}
|
||||||
|
|
||||||
bool TorrentFileManager::registerFiles(const std::string &baseDir, const TorrentFiles &files)
|
bool TorrentFileManager::registerFiles(const std::string &baseDir, const TorrentFiles &files)
|
||||||
{
|
{
|
||||||
// We have to initialize pieces here
|
// We have to initialize pieces here
|
||||||
@@ -488,7 +510,7 @@ bool TorrentFileManager::registerFiles(const std::string &baseDir, const Torrent
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentFileManager::requestPieceBlock(size_t index, uint32_t from, int64_t begin, int64_t size)
|
bool TorrentFileManager::requestPieceBlock(size_t index, uint32_t from, size_t begin, size_t size)
|
||||||
{
|
{
|
||||||
static uint32_t rid = 0;
|
static uint32_t rid = 0;
|
||||||
if (!i->intact(index) || !i->is_read_eligible(index, begin + size))
|
if (!i->intact(index) || !i->is_read_eligible(index, begin + size))
|
||||||
|
@@ -33,8 +33,8 @@
|
|||||||
struct TorrentFileInfo {
|
struct TorrentFileInfo {
|
||||||
std::string path;
|
std::string path;
|
||||||
size_t index;
|
size_t index;
|
||||||
int64_t begin;
|
size_t begin;
|
||||||
int64_t length;
|
size_t length;
|
||||||
};
|
};
|
||||||
typedef std::vector<TorrentFileInfo> TorrentFiles;
|
typedef std::vector<TorrentFileInfo> TorrentFiles;
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ public:
|
|||||||
~TorrentFileManager();
|
~TorrentFileManager();
|
||||||
|
|
||||||
const bitset *completedBits() const;
|
const bitset *completedBits() const;
|
||||||
|
size_t pending() const;
|
||||||
size_t pieceSize(size_t index) const;
|
size_t pieceSize(size_t index) const;
|
||||||
size_t completedPieces() const;
|
size_t completedPieces() const;
|
||||||
size_t totalPieces() const;
|
size_t totalPieces() const;
|
||||||
@@ -53,8 +54,9 @@ public:
|
|||||||
size_t computeDownloaded();
|
size_t computeDownloaded();
|
||||||
|
|
||||||
bool pieceDone(size_t index) const;
|
bool pieceDone(size_t index) const;
|
||||||
|
bool piecePending(size_t index) const;
|
||||||
bool registerFiles(const std::string &baseDir, const TorrentFiles &files);
|
bool registerFiles(const std::string &baseDir, const TorrentFiles &files);
|
||||||
bool requestPieceBlock(size_t index, uint32_t from, int64_t begin, int64_t size);
|
bool requestPieceBlock(size_t index, uint32_t from, size_t begin, size_t size);
|
||||||
bool writePieceBlock(size_t index, uint32_t from, DataBuffer<uint8_t> &&data);
|
bool writePieceBlock(size_t index, uint32_t from, DataBuffer<uint8_t> &&data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -86,7 +86,7 @@ bool TorrentMeta::internalParse(Dictionary &dict, Bencode &bencode)
|
|||||||
sha1.get_digest(m_checkSum);
|
sha1.get_digest(m_checkSum);
|
||||||
|
|
||||||
m_name = Bencode::cast<std::string>(info["name"]);
|
m_name = Bencode::cast<std::string>(info["name"]);
|
||||||
m_pieceLength = Bencode::cast<int64_t>(info["piece length"]);
|
m_pieceLength = Bencode::cast<size_t>(info["piece length"]);
|
||||||
|
|
||||||
std::string pieces = Bencode::cast<std::string>(info["pieces"]);
|
std::string pieces = Bencode::cast<std::string>(info["pieces"]);
|
||||||
m_sha1sums.reserve(pieces.size() / 20);
|
m_sha1sums.reserve(pieces.size() / 20);
|
||||||
@@ -111,7 +111,7 @@ bool TorrentMeta::internalParse(Dictionary &dict, Bencode &bencode)
|
|||||||
m_dirName = Bencode::cast<std::string>(info["name"]);
|
m_dirName = Bencode::cast<std::string>(info["name"]);
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
int64_t begin = 0;
|
size_t begin = 0;
|
||||||
|
|
||||||
const boost::any &any = info["files"];
|
const boost::any &any = info["files"];
|
||||||
if (any.type() == typeid(Dictionary)) {
|
if (any.type() == typeid(Dictionary)) {
|
||||||
@@ -119,7 +119,7 @@ bool TorrentMeta::internalParse(Dictionary &dict, Bencode &bencode)
|
|||||||
Dictionary v = Bencode::cast<Dictionary>(pair.second);
|
Dictionary v = Bencode::cast<Dictionary>(pair.second);
|
||||||
VectorType pathList = Bencode::cast<VectorType>(v["path"]);
|
VectorType pathList = Bencode::cast<VectorType>(v["path"]);
|
||||||
|
|
||||||
if (!parseFile(pathList, index, begin, Bencode::cast<int64_t>(v["length"])))
|
if (!parseFile(pathList, index, begin, Bencode::cast<size_t>(v["length"])))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (any.type() == typeid(VectorType)) {
|
} else if (any.type() == typeid(VectorType)) {
|
||||||
@@ -127,7 +127,7 @@ bool TorrentMeta::internalParse(Dictionary &dict, Bencode &bencode)
|
|||||||
Dictionary v = Bencode::cast<Dictionary>(f);
|
Dictionary v = Bencode::cast<Dictionary>(f);
|
||||||
VectorType pathList = Bencode::cast<VectorType>(v["path"]);
|
VectorType pathList = Bencode::cast<VectorType>(v["path"]);
|
||||||
|
|
||||||
if (!parseFile(pathList, index, begin, Bencode::cast<int64_t>(v["length"])))
|
if (!parseFile(pathList, index, begin, Bencode::cast<size_t>(v["length"])))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +135,7 @@ bool TorrentMeta::internalParse(Dictionary &dict, Bencode &bencode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int64_t length = Bencode::cast<int64_t>(info["length"]);
|
size_t length = Bencode::cast<size_t>(info["length"]);
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ bool TorrentMeta::internalParse(Dictionary &dict, Bencode &bencode)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentMeta::parseFile(const VectorType &pathList, size_t &index, int64_t &begin, int64_t length)
|
bool TorrentMeta::parseFile(const VectorType &pathList, size_t &index, size_t &begin, size_t length)
|
||||||
{
|
{
|
||||||
std::string path = "";
|
std::string path = "";
|
||||||
for (const boost::any &any : pathList) {
|
for (const boost::any &any : pathList) {
|
||||||
|
@@ -50,12 +50,12 @@ public:
|
|||||||
inline VectorType trackers() const { return m_trackers; }
|
inline VectorType trackers() const { return m_trackers; }
|
||||||
|
|
||||||
inline const uint32_t *checkSum() const { return &m_checkSum[0]; }
|
inline const uint32_t *checkSum() const { return &m_checkSum[0]; }
|
||||||
inline int64_t pieceLength() const { return m_pieceLength; }
|
inline size_t pieceLength() const { return m_pieceLength; }
|
||||||
inline size_t totalSize() const { return m_totalSize; }
|
inline size_t totalSize() const { return m_totalSize; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool internalParse(Dictionary &d, Bencode &b);
|
bool internalParse(Dictionary &d, Bencode &b);
|
||||||
bool parseFile(const VectorType &pathList, size_t &index, int64_t &begin, int64_t length);
|
bool parseFile(const VectorType &pathList, size_t &index, size_t &begin, size_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_dirName;
|
std::string m_dirName;
|
||||||
@@ -65,7 +65,7 @@ private:
|
|||||||
std::string m_mainTracker;
|
std::string m_mainTracker;
|
||||||
|
|
||||||
uint32_t m_checkSum[5];
|
uint32_t m_checkSum[5];
|
||||||
int64_t m_pieceLength;
|
size_t m_pieceLength;
|
||||||
size_t m_totalSize;
|
size_t m_totalSize;
|
||||||
|
|
||||||
TorrentFiles m_files;
|
TorrentFiles m_files;
|
||||||
|
@@ -136,7 +136,7 @@ bool Tracker::httpRequest(const TrackerQuery &r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_timeToNextRequest = std::chrono::system_clock::now()
|
m_timeToNextRequest = std::chrono::system_clock::now()
|
||||||
+ std::chrono::milliseconds(Bencode::cast<int64_t>(dict["interval"]));
|
+ std::chrono::seconds(Bencode::cast<int64_t>(dict["interval"]));
|
||||||
m_torrent->connectToPeers(dict["peers"]);
|
m_torrent->connectToPeers(dict["peers"]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ bool Tracker::udpRequest(const TrackerQuery &r)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_timeToNextRequest = std::chrono::system_clock::now() + std::chrono::milliseconds(readBE32(&response[8]));
|
m_timeToNextRequest = std::chrono::system_clock::now() + std::chrono::seconds(readBE32(&response[8]));
|
||||||
m_torrent->rawConnectPeers(&response[20], len - 20);
|
m_torrent->rawConnectPeers(&response[20], len - 20);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
41
main.cpp
41
main.cpp
@@ -27,13 +27,16 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Externed */
|
||||||
|
std::ofstream logfile;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
enum {
|
enum {
|
||||||
COL_BLACK = 0,
|
COL_BLACK = 0,
|
||||||
@@ -75,15 +78,15 @@ enum {
|
|||||||
|
|
||||||
static void print_stats(Torrent *t)
|
static void print_stats(Torrent *t)
|
||||||
{
|
{
|
||||||
const TorrentMeta *meta = t->meta();
|
TorrentMeta *meta = t->meta();
|
||||||
const TorrentFileManager *fm = t->fileManager();
|
TorrentFileManager *fm = t->fileManager();
|
||||||
|
|
||||||
printc(COL_GREEN, "%s: ", meta->name().c_str());
|
printc(COL_GREEN, "%s: ", meta->name().c_str());
|
||||||
printc(COL_YELLOW, "%.2f Mbps (%zd/%zd MB) [ %zd hash miss - %zd wasted - %.2f minutes left ] ",
|
printc(COL_YELLOW, "%.2f Mbps (%zd/%zd MB) [ %zd uploaded - %zd hash miss - %zd wasted - %.2f seconds left ] ",
|
||||||
t->downloadSpeed(), t->computeDownloaded() / 1024 / 1024, meta->totalSize() / 1024 / 1024,
|
t->downloadSpeed(), t->computeDownloaded() / 1024 / 1024, meta->totalSize() / 1024 / 1024,
|
||||||
t->hashMisses(), t->wastedBytes(), t->eta() / 60);
|
t->uploadedBytes(), t->hashMisses(), t->wastedBytes(), t->eta());
|
||||||
printc(COL_YELLOW, "[ %zd/%zd pieces %zd peers active ]\n",
|
printc(COL_YELLOW, "[ %zd/%zd/%zd pieces %zd peers active ]\n",
|
||||||
fm->completedPieces(), fm->totalPieces(), t->activePeers());
|
fm->completedPieces(), fm->pending(), fm->totalPieces(), t->activePeers());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_all_stats(Torrent *torrents, size_t total)
|
static void print_all_stats(Torrent *torrents, size_t total)
|
||||||
@@ -109,10 +112,12 @@ static void print_all_stats(Torrent *torrents, size_t total)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
bool noseed = false;
|
bool noseed = true;
|
||||||
bool nodownload = false;
|
bool nodownload = false;
|
||||||
int startport = 6881;
|
int startport = 6881;
|
||||||
|
size_t max_peers = 15;
|
||||||
std::string dldir = "Torrents";
|
std::string dldir = "Torrents";
|
||||||
|
std::string lfname = "ctorrent.log";
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
@@ -121,10 +126,12 @@ int main(int argc, char *argv[])
|
|||||||
("version,v", "print version string")
|
("version,v", "print version string")
|
||||||
("help,h", "print this help message")
|
("help,h", "print this help message")
|
||||||
("port,p", po::value(&startport), "specify start port for seeder torrents")
|
("port,p", po::value(&startport), "specify start port for seeder torrents")
|
||||||
|
("peers,m", po::value(&max_peers), "maximum amount of peers to feel sufficient with")
|
||||||
("nodownload,n", po::bool_switch(&nodownload), "do not download anything, just print info about torrents")
|
("nodownload,n", po::bool_switch(&nodownload), "do not download anything, just print info about torrents")
|
||||||
("piecesize,s", po::value(&maxRequestSize), "specify piece block size")
|
("piecesize,s", po::value(&maxRequestSize), "specify piece block size")
|
||||||
("dldir,d", po::value(&dldir), "specify downloads directory")
|
("dldir,d", po::value(&dldir), "specify downloads directory")
|
||||||
("noseed,e", po::bool_switch(&noseed), "do not seed after download has finished.")
|
("noseed,e", po::bool_switch(&noseed), "do not seed after download has finished.")
|
||||||
|
("log,l", po::value(&lfname), "specify log file name")
|
||||||
("torrents,t", po::value<std::vector<std::string>>(&files)->required()->multitoken(), "specify torrent file(s)");
|
("torrents,t", po::value<std::vector<std::string>>(&files)->required()->multitoken(), "specify torrent file(s)");
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
@@ -158,6 +165,12 @@ int main(int argc, char *argv[])
|
|||||||
if (vm.count("piecesize"))
|
if (vm.count("piecesize"))
|
||||||
maxRequestSize = 1 << (32 - __builtin_clz(maxRequestSize - 1));
|
maxRequestSize = 1 << (32 - __builtin_clz(maxRequestSize - 1));
|
||||||
|
|
||||||
|
logfile.open(lfname, std::ios_base::trunc | std::ios_base::out);
|
||||||
|
if (!logfile.is_open()) {
|
||||||
|
std::cerr << "Cannot open log file " << lfname << ": " << errno << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
size_t total = files.size();
|
size_t total = files.size();
|
||||||
size_t total_bits = 0;
|
size_t total_bits = 0;
|
||||||
size_t completed = 0;
|
size_t completed = 0;
|
||||||
@@ -221,12 +234,17 @@ int main(int argc, char *argv[])
|
|||||||
std::clog << "Downloading torrents..." << std::endl;
|
std::clog << "Downloading torrents..." << std::endl;
|
||||||
while (total_bits ^ (completed | errors)) {
|
while (total_bits ^ (completed | errors)) {
|
||||||
for (size_t i = 0; i < total; ++i) {
|
for (size_t i = 0; i < total; ++i) {
|
||||||
|
if (errors & (1 << i))
|
||||||
|
continue;
|
||||||
|
|
||||||
Torrent *t = &torrents[i];
|
Torrent *t = &torrents[i];
|
||||||
if (t->isFinished()) {
|
if (t->isFinished()) {
|
||||||
t->finish();
|
if (!noseed)
|
||||||
|
t->finish();
|
||||||
completed |= 1 << i;
|
completed |= 1 << i;
|
||||||
} else {
|
} else {
|
||||||
t->checkTrackers();
|
//if (t->activePeers() < max_peers)
|
||||||
|
t->checkTrackers();
|
||||||
if (!noseed)
|
if (!noseed)
|
||||||
t->nextConnection();
|
t->nextConnection();
|
||||||
}
|
}
|
||||||
@@ -249,7 +267,7 @@ int main(int argc, char *argv[])
|
|||||||
while (eseed ^ total_bits) {
|
while (eseed ^ total_bits) {
|
||||||
for (size_t i = 0; i < total; ++i) {
|
for (size_t i = 0; i < total; ++i) {
|
||||||
Torrent *t = &torrents[i];
|
Torrent *t = &torrents[i];
|
||||||
if (!t->nextConnection() || !t->checkTrackers())
|
if (!t->nextConnection() || (t->activePeers() < max_peers && !t->checkTrackers()))
|
||||||
eseed |= 1 << i;
|
eseed |= 1 << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +294,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete []torrents;
|
delete []torrents;
|
||||||
|
logfile.close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -79,16 +79,10 @@ public:
|
|||||||
|
|
||||||
size_t popcnt(uint64_t v) const
|
size_t popcnt(uint64_t v) const
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
|
||||||
return __builtin_popcount(v);
|
|
||||||
#elif _MSC_VER
|
|
||||||
return __popcnt64(v);
|
|
||||||
#else
|
|
||||||
// Hamming Weight
|
// Hamming Weight
|
||||||
v = v - ((v >> 1) & 0x5555555555555555);
|
v = v - ((v >> 1) & 0x5555555555555555);
|
||||||
v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
|
v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
|
||||||
return (((v + (v >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56;
|
return (((v + (v >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const { return m_size; }
|
size_t size() const { return m_size; }
|
||||||
@@ -107,7 +101,7 @@ public:
|
|||||||
src += 4;
|
src += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src + 1 < dst) {
|
if (src + 1 <= dst) {
|
||||||
set += popcnt(*(uint16_t *)src);
|
set += popcnt(*(uint16_t *)src);
|
||||||
src += 2;
|
src += 2;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user