⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 torrentclient.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    return tmp;}int TorrentClient::seedCount() const{    int tmp = 0;    foreach (PeerWireClient *client, d->connections) {        if (client->availablePieces().count(true) == d->pieceCount)            ++tmp;    }    return tmp;}TorrentClient::State TorrentClient::state() const{    return d->state;}QString TorrentClient::stateString() const{    return d->stateString;}TorrentClient::Error TorrentClient::error() const{    return d->error;}QString TorrentClient::errorString() const{    return d->errorString;}QByteArray TorrentClient::peerId() const{    return d->peerId;}QByteArray TorrentClient::infoHash() const{    return d->infoHash;}void TorrentClient::start(){    if (d->state != Idle)        return;    TorrentServer::instance()->addClient(this);    // Initialize the file manager    d->setState(Preparing);    d->fileManager.setMetaInfo(d->metaInfo);    d->fileManager.setDestinationFolder(d->destinationFolder);    d->fileManager.setCompletedPieces(d->completedPieces);    d->fileManager.start(QThread::LowestPriority);    d->fileManager.startDataVerification();}void TorrentClient::stop(){    if (d->state == Stopping)        return;    TorrentServer::instance()->removeClient(this);    // Update the state    State oldState = d->state;    d->setState(Stopping);    // Stop the timer    if (d->transferRateTimer) {        killTimer(d->transferRateTimer);        d->transferRateTimer = 0;    }    // Abort all existing connections    foreach (PeerWireClient *client, d->connections)        client->abort();    d->connections.clear();    // Perhaps stop the tracker    if (oldState > Preparing) {        d->trackerClient.stop();    } else {        d->setState(Idle);        emit stopped();    }}void TorrentClient::setPaused(bool paused){    if (paused) {        // Abort all connections, and set the max number of        // connections to 0. Keep the list of peers, so we can quickly        // resume later.        d->setState(Paused);        foreach (PeerWireClient *client, d->connections)            client->abort();        d->connections.clear();        TorrentServer::instance()->removeClient(this);    } else {        // Restore the max number of connections, and start the peer        // connector. We should also quickly start receiving incoming        // connections.        d->setState(d->completedPieces.count(true) == d->fileManager.pieceCount()                    ? Seeding : Searching);        connectToPeers();        TorrentServer::instance()->addClient(this);    }}void TorrentClient::timerEvent(QTimerEvent *event){    if (event->timerId() == d->uploadScheduleTimer) {        // Update the state of who's choked and who's not        scheduleUploads();        return;    }    if (event->timerId() != d->transferRateTimer) {        QObject::timerEvent(event);        return;    }    // Calculate average upload/download rate    qint64 uploadBytesPerSecond = 0;    qint64 downloadBytesPerSecond = 0;    for (int i = 0; i < RateControlWindowLength; ++i) {        uploadBytesPerSecond += d->uploadRate[i];        downloadBytesPerSecond += d->downloadRate[i];    }    uploadBytesPerSecond /= qint64(RateControlWindowLength);    downloadBytesPerSecond /= qint64(RateControlWindowLength);    for (int i = RateControlWindowLength - 2; i >= 0; --i) {        d->uploadRate[i + 1] = d->uploadRate[i];        d->downloadRate[i + 1] = d->downloadRate[i];    }    d->uploadRate[0] = 0;    d->downloadRate[0] = 0;    emit uploadRateUpdated(int(uploadBytesPerSecond));    emit downloadRateUpdated(int(downloadBytesPerSecond));    // Stop the timer if there is no activity.    if (downloadBytesPerSecond == 0 && uploadBytesPerSecond == 0) {        killTimer(d->transferRateTimer);        d->transferRateTimer = 0;    }}void TorrentClient::sendToPeer(int readId, int pieceIndex, int begin, const QByteArray &data){    // Send the requested block to the peer if the client connection    // still exists; otherwise do nothing. This slot is called by the    // file manager after it has read a block of data.    PeerWireClient *client = d->readIds.value(readId);    if (client) {        if ((client->peerWireState() & PeerWireClient::ChokingPeer) == 0)            client->sendBlock(pieceIndex, begin, data);    }    d->readIds.remove(readId);}void TorrentClient::fullVerificationDone(){    // Update our list of completed and incomplete pieces.    d->completedPieces = d->fileManager.completedPieces();    d->incompletePieces.resize(d->completedPieces.size());    d->pieceCount = d->completedPieces.size();    for (int i = 0; i < d->fileManager.pieceCount(); ++i) {        if (!d->completedPieces.testBit(i))            d->incompletePieces.setBit(i);    }    updateProgress();    // If the checksums show that what the dumped state thought was    // partial was in fact complete, then we trust the checksums.    QMap<int, TorrentPiece *>::Iterator it = d->pendingPieces.begin();    while (it != d->pendingPieces.end()) {        if (d->completedPieces.testBit(it.key()))            it = d->pendingPieces.erase(it);        else            ++it;    }    d->uploadScheduleTimer = startTimer(UploadScheduleInterval);    // Start the server    TorrentServer *server = TorrentServer::instance();    if (!server->isListening()) {        // Set up the peer wire server        for (int i = ServerMinPort; i <= ServerMaxPort; ++i) {            if (server->listen(QHostAddress::Any, i))                break;        }        if (!server->isListening()) {            d->setError(ServerError);            return;        }    }    d->setState(d->completedPieces.count(true) == d->pieceCount ? Seeding : Searching);    // Start the tracker client    d->trackerClient.setUploadCount(d->uploadedBytes);    d->trackerClient.setDownloadCount(d->downloadedBytes);    d->trackerClient.start(d->metaInfo);}void TorrentClient::pieceVerified(int pieceIndex, bool ok){    TorrentPiece *piece = d->pendingPieces.value(pieceIndex);    // Remove this piece from all payloads    QMultiMap<PeerWireClient *, TorrentPiece *>::Iterator it = d->payloads.begin();    while (it != d->payloads.end()) {        if (it.value()->index == pieceIndex)            it = d->payloads.erase(it);        else            ++it;    }    if (!ok) {        // If a piece did not pass the SHA1 check, we'll simply clear        // its state, and the scheduler will re-request it        piece->inProgress = false;        piece->completedBlocks.fill(false);        piece->requestedBlocks.fill(false);        d->callScheduler();        return;    }    // Update the peer list so we know who's still interesting.    foreach (TorrentPeer *peer, d->peers) {        if (!peer->interesting)            continue;        bool interesting = false;        for (int i = 0; i < d->pieceCount; ++i) {            if (peer->pieces.testBit(i) && d->incompletePieces.testBit(i)) {                interesting = true;                break;            }        }        peer->interesting = interesting;    }    // Delete the piece and update our structures.    delete piece;    d->pendingPieces.remove(pieceIndex);    d->completedPieces.setBit(pieceIndex);    d->incompletePieces.clearBit(pieceIndex);    // Notify connected peers.    foreach (PeerWireClient *client, d->connections) {        if (client->state() == QAbstractSocket::ConnectedState            && !client->availablePieces().testBit(pieceIndex)) {            client->sendPieceNotification(pieceIndex);        }    }    // Notify the tracker if we've entered Seeding status; otherwise    // call the scheduler.    int completed = d->completedPieces.count(true);    if (completed == d->pieceCount) {        if (d->state != Seeding) {            d->setState(Seeding);            d->trackerClient.start(d->metaInfo);        }    } else {        if (completed == 1)            d->setState(Downloading);        else if (d->incompletePieces.count(true) < 5 && d->pendingPieces.size() > d->incompletePieces.count(true))            d->setState(Endgame);        d->callScheduler();    }    updateProgress();}void TorrentClient::handleFileError(){    if (d->state == Paused)        return;    setPaused(true);    emit error(FileError);}void TorrentClient::connectToPeers(){    d->connectingToClients = false;    if (d->state == Stopping || d->state == Idle || d->state == Paused)        return;    if (d->state == Searching)        d->setState(Connecting);    // Find the list of peers we are not currently connected to, where    // the more interesting peers are listed more than once.    QList<TorrentPeer *> weighedPeers = weighedFreePeers();    // Start as many connections as we can    while (!weighedPeers.isEmpty() && ConnectionManager::instance()->canAddConnection()           && (rand() % (ConnectionManager::instance()->maxConnections() / 2))) {        PeerWireClient *client = new PeerWireClient(ConnectionManager::instance()->clientId(), this);        RateController::instance()->addSocket(client);        ConnectionManager::instance()->addConnection(client);        initializeConnection(client);        d->connections << client;        // Pick a random peer from the list of weighed peers.        TorrentPeer *peer = weighedPeers.takeAt(rand() % weighedPeers.size());        weighedPeers.removeAll(peer);        peer->connectStart = QDateTime::currentDateTime().toTime_t();        peer->lastVisited = peer->connectStart;        // Connect to the peer.        client->setPeer(peer);        client->connectToHost(peer->address, peer->port);    }}QList<TorrentPeer *> TorrentClient::weighedFreePeers() const{    QList<TorrentPeer *> weighedPeers;    // Generate a list of peers that we want to connect to.    uint now = QDateTime::currentDateTime().toTime_t();    QList<TorrentPeer *> freePeers;    QMap<QString, int> connectionsPerPeer;    foreach (TorrentPeer *peer, d->peers) {        bool busy = false;        foreach (PeerWireClient *client, d->connections) {            if (client->state() == PeerWireClient::ConnectedState                && client->peerAddress() == peer->address                && client->peerPort() == peer->port) {                if (++connectionsPerPeer[peer->address.toString()] >= MaxConnectionPerPeer) {                    busy = true;                    break;                }            }        }        if (!busy && (now - peer->lastVisited) > uint(MinimumTimeBeforeRevisit))            freePeers << peer;    }    // Nothing to connect to    if (freePeers.isEmpty())        return weighedPeers;    // Assign points based on connection speed and pieces available.    QList<QPair<int, TorrentPeer *> > points;    foreach (TorrentPeer *peer, freePeers) {        int tmp = 0;        if (peer->interesting) {            tmp += peer->numCompletedPieces;            if (d->state == Seeding)                tmp = d->pieceCount - tmp;            if (!peer->connectStart) // An unknown peer is as interesting as a seed                tmp += d->pieceCount;            // 1/5 of the total score for each second below 5 it takes to            // connect.            if (peer->connectTime < 5)                tmp += (d->pieceCount / 10) * (5 - peer->connectTime);        }        points << QPair<int, TorrentPeer *>(tmp, peer);    }    qSort(points);    // Minimize the list so the point difference is never more than 1.    typedef QPair<int,TorrentPeer*> PointPair;    QMultiMap<int, TorrentPeer *> pointMap;    int lowestScore = 0;    int lastIndex = 0;    foreach (PointPair point, points) {        if (point.first > lowestScore) {            lowestScore = point.first;            ++lastIndex;        }        pointMap.insert(lastIndex, point.second);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -