|  | Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# peerwireclient.h Example File
network/torrent/peerwireclient.h

    /****************************************************************************
    **
    ** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.
    **
    ** This file is part of the example classes of the Qt Toolkit.
    **
    ** Licensees holding valid Qt Preview licenses may use this file in
    ** accordance with the Qt Preview License Agreement provided with the
    ** Software.
    **
    ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
    ** information about Qt Commercial License Agreements.
    **
    ** Contact info@trolltech.com if any conditions of this licensing are
    ** not clear to you.
    **
    ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
    ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    **
    ****************************************************************************/

    #ifndef PEERWIRECLIENT_H
    #define PEERWIRECLIENT_H

    class QHostAddress;
    class QTimerEvent;
    class TorrentPeer;

    #include <QBitArray>
    #include <QList>
    #include <QTcpSocket>

    struct TorrentBlock
    {
        inline TorrentBlock(int p, int o, int l)
            : pieceIndex(p), offset(o), length(l)
        {
        }
        inline bool operator==(const TorrentBlock &other) const
        {
            return pieceIndex == other.pieceIndex
                    && offset == other.offset
                    && length == other.length;
        }

        int pieceIndex;
        int offset;
        int length;
    };

    class PeerWireClient : public QTcpSocket
    {
        Q_OBJECT

    public:
        enum PeerWireStateFlag {
            ChokingPeer = 0x1,
            InterestedInPeer = 0x2,
            ChokedByPeer = 0x4,
            PeerIsInterested = 0x8
        };
        Q_DECLARE_FLAGS(PeerWireState, PeerWireStateFlag)

        PeerWireClient(const QByteArray &peerId, QObject *parent = 0);
        void initialize(const QByteArray &infoHash, int pieceCount);

        void setPeer(TorrentPeer *peer);
        TorrentPeer *peer() const;

        // State
        inline PeerWireState peerWireState() const { return pwState; }
        QBitArray availablePieces() const;
        QList<TorrentBlock> incomingBlocks() const;

        // Protocol
        void chokePeer();
        void unchokePeer();
        void sendInterested();
        void sendKeepAlive();
        void sendNotInterested();
        void sendPieceNotification(int piece);
        void sendPieceList(const QBitArray &bitField);
        void requestBlock(int piece, int offset, int length);
        void cancelRequest(int piece, int offset, int length);
        void sendBlock(int piece, int offset, const QByteArray &data);

        // Rate control
        qint64 writeToSocket(qint64 bytes);
        qint64 readFromSocket(qint64 bytes);
        qint64 downloadSpeed() const;
        qint64 uploadSpeed() const;

        bool canTransferMore() const;
        qint64 bytesAvailable() const { return incomingBuffer.size(); }
        qint64 socketBytesAvailable() const { return QTcpSocket::bytesAvailable(); }

    signals:
        void infoHashReceived(const QByteArray &infoHash);
        void readyToTransfer();

        void choked();
        void unchoked();
        void interested();
        void notInterested();

        void piecesAvailable(const QBitArray &pieces);
        void blockRequested(int pieceIndex, int begin, int length);
        void blockReceived(int pieceIndex, int begin, const QByteArray &data);

        void bytesReceived(qint64 size);

    protected slots:
        void timerEvent(QTimerEvent *event);

    protected:
        qint64 readData(char *data, qint64 maxlen);
        qint64 readLineData(char *data, qint64 maxlen);
        qint64 writeData(const char *data, qint64 len);

    private slots:
        void sendHandShake();
        void processIncomingData();

    private:
        // Data waiting to be read/written
        QByteArray incomingBuffer;
        QByteArray outgoingBuffer;

        struct BlockInfo {
            int pieceIndex;
            int offset;
            int length;
            QByteArray block;
        };
        QList<BlockInfo> pendingBlocks;
        int pendingBlockSizes;
        QList<TorrentBlock> incoming;

        enum PacketType {
            ChokePacket = 0,
            UnchokePacket = 1,
            InterestedPacket = 2,
            NotInterestedPacket = 3,
            HavePacket = 4,
            BitFieldPacket = 5,
            RequestPacket = 6,
            PiecePacket = 7,
            CancelPacket = 8
        };

        // State
        PeerWireState pwState;
        bool receivedHandShake;
        bool gotPeerId;
        bool sentHandShake;
        int nextPacketLength;

        // Upload/download speed records
        qint64 uploadSpeedData[8];
        qint64 downloadSpeedData[8];
        int transferSpeedTimer;

        // Timeout handling
        int timeoutTimer;
        int pendingRequestTimer;
        bool invalidateTimeout;
        int keepAliveTimer;

        // Checksum, peer ID and set of available pieces
        QByteArray infoHash;
        QByteArray peerIdString;
        QBitArray peerPieces;
        TorrentPeer *torrentPeer;
    };

    Q_DECLARE_OPERATORS_FOR_FLAGS(PeerWireClient::PeerWireState)

    #endif