|  | 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 documentation 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.
        **
        ****************************************************************************/

        #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