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

📄 peerwireclient.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.**** This file is part of the example classes of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "peerwireclient.h"#include <QTimerEvent>static const int PendingRequestTimeout = 60 * 1000;static const int ClientTimeout = 120 * 1000;static const int ConnectTimeout = 60 * 1000;static const int KeepAliveInterval = 30 * 1000;static const int RateControlTimerDelay = 2000;static const int MinimalHeaderSize = 48;static const int FullHeaderSize = 68;static const char ProtocolId[] = "BitTorrent protocol";static const char ProtocolIdSize = 19;// Reads a 32bit unsigned int from data in network order.static inline quint32 fromNetworkData(const char *data){    const unsigned char *udata = (const unsigned char *)data;    return (quint32(udata[0]) << 24)        | (quint32(udata[1]) << 16)        | (quint32(udata[2]) << 8)        | (quint32(udata[3]));}// Writes a 32bit unsigned int from num to data in network order.static inline void toNetworkData(quint32 num, char *data){    unsigned char *udata = (unsigned char *)data;    udata[3] = (num & 0xff);    udata[2] = (num & 0xff00) >> 8;    udata[1] = (num & 0xff0000) >> 16;    udata[0] = (num & 0xff000000) >> 24;}// Constructs an unconnected PeerWire client and starts the connect timer.PeerWireClient::PeerWireClient(const QByteArray &peerId, QObject *parent)    : QTcpSocket(parent), pendingBlockSizes(0),      pwState(ChokingPeer | ChokedByPeer), receivedHandShake(false), gotPeerId(false),      sentHandShake(false), nextPacketLength(-1), pendingRequestTimer(0), invalidateTimeout(false),      keepAliveTimer(0), torrentPeer(0){    memset(uploadSpeedData, 0, sizeof(uploadSpeedData));    memset(downloadSpeedData, 0, sizeof(downloadSpeedData));    transferSpeedTimer = startTimer(RateControlTimerDelay);    timeoutTimer = startTimer(ConnectTimeout);    peerIdString = peerId;    connect(this, SIGNAL(readyRead()), this, SIGNAL(readyToTransfer()));    connect(this, SIGNAL(connected()), this, SIGNAL(readyToTransfer()));}// Registers the peer ID and SHA1 sum of the torrent, and initiates// the handshake.void PeerWireClient::initialize(const QByteArray &infoHash, int pieceCount){    this->infoHash = infoHash;    peerPieces.resize(pieceCount);    if (!sentHandShake)        sendHandShake();}void PeerWireClient::setPeer(TorrentPeer *peer){    torrentPeer = peer;}TorrentPeer *PeerWireClient::peer() const{    return torrentPeer;}QBitArray PeerWireClient::availablePieces() const{    return peerPieces;}QList<TorrentBlock> PeerWireClient::incomingBlocks() const{    return incoming;}// Sends a "choke" message, asking the peer to stop requesting blocks.void PeerWireClient::chokePeer(){    const char message[] = {0, 0, 0, 1, 0};    write(message, sizeof(message));    pwState |= ChokingPeer;    // After receiving a choke message, the peer will assume all    // pending requests are lost.    pendingBlocks.clear();    pendingBlockSizes = 0;}// Sends an "unchoke" message, allowing the peer to start/resume// requesting blocks.void PeerWireClient::unchokePeer(){    const char message[] = {0, 0, 0, 1, 1};    write(message, sizeof(message));    pwState &= ~ChokingPeer;    if (pendingRequestTimer)        killTimer(pendingRequestTimer);}// Sends a "keep-alive" message to prevent the peer from closing// the connection when there's no activityvoid PeerWireClient::sendKeepAlive(){    const char message[] = {0, 0, 0, 0};    write(message, sizeof(message));}// Sends an "interested" message, informing the peer that it has got// pieces that we'd like to download.void PeerWireClient::sendInterested(){    const char message[] = {0, 0, 0, 1, 2};    write(message, sizeof(message));    pwState |= InterestedInPeer;    // After telling the peer that we're interested, we expect to get    // unchoked within a certain timeframe; otherwise we'll drop the    // connection.    if (pendingRequestTimer)        killTimer(pendingRequestTimer);    pendingRequestTimer = startTimer(PendingRequestTimeout);}// Sends a "not interested" message, informing the peer that it does// not have any pieces that we'd like to download.void PeerWireClient::sendNotInterested(){    const char message[] = {0, 0, 0, 1, 3};    write(message, sizeof(message));    pwState &= ~InterestedInPeer;}// Sends a piece notification / a "have" message, informing the peer// that we have just downloaded a new piece.void PeerWireClient::sendPieceNotification(int piece){    if (!sentHandShake)        sendHandShake();    char message[] = {0, 0, 0, 5, 4, 0, 0, 0, 0};    toNetworkData(piece, &message[5]);    write(message, sizeof(message));}// Sends the complete list of pieces that we have downloaded.void PeerWireClient::sendPieceList(const QBitArray &bitField){    // The bitfield message may only be sent immediately after the    // handshaking sequence is completed, and before any other    // messages are sent.    if (!sentHandShake)        sendHandShake();    // Don't send the bitfield if it's all zeros.    if (bitField.count(true) == 0)	return;    int bitFieldSize = bitField.size();    int size = (bitFieldSize + 7) / 8;    QByteArray bits(size, '\0');    for (int i = 0; i < bitFieldSize; ++i) {        if (bitField.testBit(i)) {            quint32 byte = quint32(i) / 8;            quint32 bit = quint32(i) % 8;            bits[byte] = uchar(bits.at(byte)) | (1 << (7 - bit));        }    }    char message[] = {0, 0, 0, 1, 5};    toNetworkData(bits.size() + 1, &message[0]);    write(message, sizeof(message));    write(bits);}// Sends a request for a block.void PeerWireClient::requestBlock(int piece, int offset, int length){    char message[] = {0, 0, 0, 1, 6};    toNetworkData(13, &message[0]);    write(message, sizeof(message));    char numbers[4 * 3];    toNetworkData(piece, &numbers[0]);    toNetworkData(offset, &numbers[4]);    toNetworkData(length, &numbers[8]);    write(numbers, sizeof(numbers));    incoming << TorrentBlock(piece, offset, length);    // After requesting a block, we expect the block to be sent by the    // other peer within a certain number of seconds. Otherwise, we    // drop the connection.    if (pendingRequestTimer)        killTimer(pendingRequestTimer);    pendingRequestTimer = startTimer(PendingRequestTimeout);}// Cancels a request for a block.void PeerWireClient::cancelRequest(int piece, int offset, int length){    char message[] = {0, 0, 0, 1, 8};    toNetworkData(13, &message[0]);    write(message, sizeof(message));    char numbers[4 * 3];    toNetworkData(piece, &numbers[0]);    toNetworkData(offset, &numbers[4]);    toNetworkData(length, &numbers[8]);    write(numbers, sizeof(numbers));    incoming.removeAll(TorrentBlock(piece, offset, length));}// Sends a block to the peer.void PeerWireClient::sendBlock(int piece, int offset, const QByteArray &data){    QByteArray block;    char message[] = {0, 0, 0, 1, 7};    toNetworkData(9 + data.size(), &message[0]);    block += QByteArray(message, sizeof(message));    char numbers[4 * 2];    toNetworkData(piece, &numbers[0]);    toNetworkData(offset, &numbers[4]);    block += QByteArray(numbers, sizeof(numbers));    block += data;    BlockInfo blockInfo;    blockInfo.pieceIndex = piece;    blockInfo.offset = offset;    blockInfo.length = data.size();    blockInfo.block = block;    pendingBlocks << blockInfo;    pendingBlockSizes += block.size();    if (pendingBlockSizes > 32 * 16384) {        chokePeer();        unchokePeer();        return;    }    emit readyToTransfer();}// Attempts to write 'bytes' bytes to the socket from the buffer.// This is used by RateController, which precisely controls how much// each client can write.qint64 PeerWireClient::writeToSocket(qint64 bytes){    qint64 totalWritten = 0;    do {        if (outgoingBuffer.isEmpty() && !pendingBlocks.isEmpty()) {            BlockInfo block = pendingBlocks.takeFirst();            pendingBlockSizes -= block.length;            outgoingBuffer += block.block;        }        qint64 written = QTcpSocket::writeData(outgoingBuffer.constData(),                                               qMin<qint64>(bytes - totalWritten, outgoingBuffer.size()));        if (written <= 0)            return totalWritten ? totalWritten : written;                totalWritten += written;        uploadSpeedData[0] += written;        outgoingBuffer.remove(0, written);    } while (totalWritten < bytes && (!outgoingBuffer.isEmpty() || !pendingBlocks.isEmpty()));    return totalWritten;}// Attempts to read at most 'bytes' bytes from the socket.qint64 PeerWireClient::readFromSocket(qint64 bytes)

⌨️ 快捷键说明

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