/*************************************************************************** * Copyright (C) 2005 by Joris Guisson * * joris.guisson@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef BTPEERMANAGER_H #define BTPEERMANAGER_H #include #include #include #include #include "globals.h" #include "peerid.h" #include #include namespace mse { class StreamSocket; } namespace bt { class Peer; class ChunkManager; class Torrent; class Authenticate; class ChunkCounter; const Uint32 MAX_SIMULTANIOUS_AUTHS = 20; /** * @author Joris Guisson * @brief Manages all the Peers * * This class manages all Peer objects. * It can also open connections to other peers. */ class PeerManager : public TQObject { Q_OBJECT public: /** * Constructor. * @param tor The Torrent */ PeerManager(Torrent & tor); virtual ~PeerManager(); /** * Check for new connections, update down and upload speed of each Peer. * Initiate new connections. */ void update(); /** * Remove dead peers. * @return The number of dead ones removed */ Uint32 clearDeadPeers(); /** * Get the i'th Peer. * @param index * @return Peer or 0 if out of range */ Peer* getPeer(Uint32 index) {return peer_list.at(index);} /** * Find a Peer based on it's ID * @param peer_id The ID * @return A Peer or 0, if nothing could be found */ Peer* findPeer(Uint32 peer_id); /** * Try to connect to some peers */ void connectToPeers(); /** * Close all Peer connections. */ void closeAllConnections(); /** * Start listening to incoming requests. */ void start(); /** * Stop listening to incoming requests. */ void stop(); /** * Kill all peers who have been choked longer then @a older_then time. * @param older_then Time in milliseconds */ void killChokedPeers(Uint32 older_then); Uint32 getNumConnectedPeers() const {return peer_list.count();} Uint32 getNumPending() const {return num_pending;} static void setMaxConnections(Uint32 max); static Uint32 getMaxConnections() {return max_connections;} static void setMaxTotalConnections(Uint32 max); static Uint32 getMaxTotalConnections() {return max_total_connections;} static Uint32 getTotalConnections() {return total_connections;} /// Is the peer manager started bool isStarted() const {return started;} /// Get the Torrent Torrent & getTorrent() {return tor;} /** * A new connection is ready for this PeerManager. * @param sock The socket * @param peer_id The Peer's ID * @param support What extensions the peer supports */ void newConnection(mse::StreamSocket* sock,const PeerID & peer_id,Uint32 support); /** * Add a potential peer * @param pp The PotentialPeer */ void addPotentialPeer(const kt::PotentialPeer & pp); /** * Kills all connections to seeders. * This is used when torrent download gets finished * and we should drop all connections to seeders */ void killSeeders(); /** * Kills all peers that are not interested for a long time. * This should be used when torrent is seeding ONLY. */ void killUninterested(); /// Get a BitSet of all available chunks const BitSet & getAvailableChunksBitSet() const {return available_chunks;} /// Get the chunk counter. ChunkCounter & getChunkCounter() {return *cnt;}; /// Are we connected to a Peer given it's PeerID ? bool connectedTo(const PeerID & peer_id); /** * A peer has authenticated. * @param auth The Authenticate object * @param ok Wether or not the attempt was succesfull */ void peerAuthenticated(Authenticate* auth,bool ok); /** * Save the IP's and port numbers of all peers. */ void savePeerList(const TQString & file); /** * Load the peer list again and add them to the potential peers */ void loadPeerList(const TQString & file); typedef TQPtrList::const_iterator CItr; CItr beginPeerList() const {return peer_list.begin();} CItr endPeerList() const {return peer_list.end();} /// Is PEX eanbled bool isPexEnabled() const {return pex_on;} /// Enable or disable PEX void setPexEnabled(bool on); /// Set the group IDs of each peer void setGroupIDs(Uint32 up,Uint32 down); public slots: /** * A PeerSource, has new potential peers. * @param ps The PeerSource */ void peerSourceReady(kt::PeerSource* ps); private: void updateAvailableChunks(); bool killBadPeer(); void createPeer(mse::StreamSocket* sock,const PeerID & peer_id,Uint32 support,bool local); bool connectedTo(const TQString & ip,Uint16 port) const; private slots: void onHave(Peer* p,Uint32 index); void onBitSetRecieved(const BitSet & bs); void onRerunChoker(); void pex(const TQByteArray & arr); signals: void newPeer(Peer* p); void peerKilled(Peer* p); void stopped(); private: PtrMap peer_map; TQPtrList peer_list; TQPtrList killed; Torrent & tor; bool started; BitSet available_chunks; ChunkCounter* cnt; Uint32 num_pending; bool pex_on; static Uint32 max_connections; static Uint32 max_total_connections; static Uint32 total_connections; std::multimap potential_peers; typedef std::multimap::iterator PPItr; }; } #endif