/** ** File ......... Session.cpp ** Published .... 2005-06-14 ** Author ....... grymse@alhem.net **/ /* Copyright (C) 2005 Anders Hedstrom 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef _WIN32 #pragma warning(disable:4786) #define random rand typedef unsigned __int32 uint32_t; #endif #include #include #include #include #include #include "PeerHandler.h" #include "Peer.h" #include "bitmap_t.h" #include "Piece.h" #include "pSocket.h" #include "FileManager.h" #include "Clock.h" #include "Session.h" #define DEB(x) x Session::Session(SocketHandler& h,const std::string& hash) :m_handler(h) ,m_info_hash(hash) ,m_piece_length(0) ,m_length(0) ,m_number_of_pieces(0) ,m_last_length(0) ,m_interval(60) ,m_t_tracker(0) //,m_bitmap(NULL) ,m_prev_offset(0) ,m_prev_length(0) ,m_length_one(0) ,m_filemanager(NULL) ,m_b_check_complete(false) ,m_demon(false) { DEB( printf("%s\n", hash.c_str());) Uid uid; memcpy(m_peer_id, "-++0001-", 8); memcpy(m_peer_id + 8, uid.GetBuf(), 12); } Session::~Session() { Save(); while (m_files.size()) { file_v::iterator it = m_files.begin(); file_t *p = *it; delete p; m_files.erase(it); } while (m_peers.size()) { peer_v::iterator it = m_peers.begin(); Peer *p = *it; delete p; m_peers.erase(it); } while (m_complete.size()) { piece_v::iterator it = m_complete.begin(); Piece *p = *it; delete p; m_complete.erase(it); } while (m_incomplete.size()) { piece_v::iterator it = m_incomplete.begin(); Piece *p = *it; delete p; m_incomplete.erase(it); } if (m_filemanager) delete m_filemanager; } void Session::AddFile(int64_t length) { AddFile(m_name, length); m_length_one = length; } void Session::AddFile(const std::string& path,int64_t length) { DEB(printf(" %s (%lld @ %lld)\n", path.c_str(), length, m_prev_offset + m_prev_length);) file_t *p = new file_t(path, length); m_length += length; p -> offset = m_prev_offset + m_prev_length; m_files.push_back(p); m_prev_offset = p -> offset; m_prev_length = p -> length; } // load peers, complete, incomplete void Session::Load() { std::string filename = GetBitmapFilename(); FILE *fil = fopen(filename.c_str(), "rb"); if (fil) { size_t q; fread(&q, sizeof(size_t), 1, fil); // number of peers while (q--) { char c; char ip[100]; fread(&c, 1, 1, fil); // length of ip fread(ip, 1, c, fil); ip[ (int)c] = 0; char id[20]; fread(id, 1, 20, fil); port_t port; fread(&port, sizeof(port_t), 1, fil); if (!GetPeer(ip) && port) { Peer *p = new Peer(Handler(),m_info_hash,ip,static_cast(id).substr(0,20),port); AddPeer(p); } } load_piece_v(fil, m_complete); load_piece_v(fil, m_incomplete); fclose(fil); // ... for (piece_v::iterator it = m_complete.begin(); it != m_complete.end(); it++) { Piece *p = *it; p -> ClearRequested(); } { for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; p -> ClearRequested(); } } // verify loaded data /* while (m_peers.size()) { peer_v::iterator it = m_peers.begin(); Peer *peer = *it; delete peer; m_peers.erase(it); } */ return; } // no file to load for (size_t i = 0; i < m_number_of_pieces; i++) { Piece *p; if (i < m_number_of_pieces - 1) { p = new Piece(i, m_piece_length); } else { p = new Piece(i, m_last_length); } m_incomplete.push_back(p); } Verify(); } // save peers, complete, incomplete void Session::Save() { std::string filename = GetBitmapFilename(); static_cast(Handler()).mkpath( filename ); FILE *fil = fopen(filename.c_str(), "wb"); if (fil) { size_t q = m_peers.size(); fwrite(&q, sizeof(size_t), 1, fil); for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; char c = peer -> GetIP().size(); fwrite(&c, 1, 1, fil); fwrite(peer -> GetIP().c_str(), 1, c, fil); fwrite(peer -> GetID().c_str(), 1, 20, fil); port_t p = peer -> GetPort(); fwrite(&p, sizeof(port_t), 1, fil); } save_piece_v(fil, m_complete); save_piece_v(fil, m_incomplete); fclose(fil); } DEB( printf("Save: %s\n", m_info_hash.c_str());) } std::string Session::GetBitmapFilename() { std::string torrentdir = static_cast(Handler()).GetTorrentDirectory(); return torrentdir + "/" + m_info_hash + "/." + m_info_hash; } Peer *Session::GetPeer(const std::string& ip) { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *p = *it; if (p -> GetIP() == ip) return p; } return NULL; } std::string Session::GetAnnounceUrl(const std::string& event) { std::string url; char slask[200]; url = GetAnnounce(); url += "?info_hash="; for (size_t i = 0; i < 40; i += 2) { url += '%'; url += m_info_hash.substr(i,2); } strcpy(slask,"&peer_id="); { for (size_t i = 0; i < 20; i++) { unsigned short x = m_peer_id[i]; sprintf(slask + strlen(slask),"%%%02x",x); } } url += slask; // peer_id url += "&ip=" + static_cast(Handler()).GetExternIP(); sprintf(slask,"&port=%d", static_cast(Handler()).GetListenPort() ); url += slask; // port url += "&uploaded=0"; url += "&downloaded=0"; url += "&left=1"; if (event.size()) url += "&event=" + event; url += "&numwant=" + Utility::l2string(static_cast(Handler()).GetMinPeers() * 2); return url; } void Session::SetPieceLength(int64_t x) { m_piece_length = x; if (m_piece_length % SLICE) { printf("+---------------------------------\n"); printf(" Odd piece length: %lld\n", x); printf("+---------------------------------\n"); } } void Session::SetPieces(const std::string& x) { m_pieces = x; m_number_of_pieces = x.size() / 20; m_last_length = m_length % m_piece_length; if (!m_last_length) m_last_length = m_piece_length; } void Session::AddConnect() { PeerHandler& ref = static_cast(Handler()); std::vector available; time_t now = time(NULL); for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; if (peer -> Failed()) { m_peers.erase(it); break; } } { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; if (!peer -> Connected() && now > peer -> GetChokeTime() + ref.GetChokeTimer() && !peer -> Tried() && !peer -> Failed()) { available.push_back(peer); } } } size_t q; if ((q = available.size()) > 0) { Peer *peer = available[random() % q]; pSocket *p = new pSocket(Handler(), m_info_hash, (unsigned char *)peer -> GetID().c_str()); p -> Open(peer -> GetIP(), peer -> GetPort()); p -> SetDeleteByHandler(); Handler().Add(p); peer -> SetTried(); } else { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; peer -> SetTried(false); } } } bool Session::GetRandomNotRequested(Peer *peer,size_t& piece,size_t& offset,size_t& length) { std::map > mmap; size_t q[1000]; size_t max = 0; memset(q, 0, sizeof(size_t[1000])); //DEB(printf("Find most complete piece(s)\n");) for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (peer -> IsSet(p -> GetNumber()) && !p -> AllRequested()) { size_t n = p -> NumberComplete(); n = p -> NumberRequested(); if (n < 1000) { q[n]++; mmap[n].push_back(p); max = MAX(max,n); } } } /* DEB( if (max > 0) { printf("Top pieces(%d/%d):", max, m_piece_length / SLICE); for (std::vector::iterator it = mmap[max].begin(); it != mmap[max].end(); it++) { Piece *p = *it; printf(" %d", p -> GetNumber()); } printf("\n"); }) */ //DEB(printf("Select most complete piece\n");) while (max > 0) { if (q[max] && (!max || (random() % 13 > 0)) ) { std::vector& ref = mmap[max]; Piece *p = ref[random() % ref.size()]; piece = p -> GetNumber(); return p -> GetRandomNotRequested(offset, length); } max--; } // { if (q[max]) { std::vector& ref = mmap[max]; Piece *p = ref[random() % ref.size()]; piece = p -> GetNumber(); return p -> GetRandomNotRequested(offset, length); } } // find rarest piece to begin with /* if (q[max]) { DEB(printf("Find rarest piece\n");) std::vector& ref = mmap[max]; std::vector available; size_t qinst = 9999999; for (std::vector::iterator it = ref.begin(); it != ref.end(); it++) { Piece *p = *it; size_t n = GetInstances(p -> GetNumber()); if (n && n < qinst) { while (available.size()) available.erase(available.begin()); available.push_back(p); qinst = n; } else if (n == qinst) { available.push_back(p); } } size_t q; if ((q = available.size()) > 0) { Piece *p = available[random() % q]; piece = p -> GetNumber(); DEB(printf("Random Rare: %d (out of %d available)\n", piece, q);) return p -> GetRandomNotRequested(offset, length); } } */ return false; } Request *Session::AddRequest(Peer *peer,size_t piece,size_t offset,size_t length) { pSocket *sock = peer -> PeerSocket(); for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (p -> GetNumber() == piece) { // TODO: check status p -> SetRequested(offset, length); if (sock) { sock -> SendRequest(piece, offset, length); } return new Request(piece, offset, length); } } return NULL; } void Session::RemoveRequest(Peer *peer,size_t piece,size_t offset,size_t length) { pSocket *sock = peer -> PeerSocket(); for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (p -> GetNumber() == piece) { // TODO: check status p -> SetRequested(offset, 0); if (sock) { sock -> SendCancel(piece, offset, length); } return; } } } void Session::SaveSlice(size_t piece,size_t offset,size_t length,unsigned char *buf) { for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (p -> GetNumber() == piece) { p -> SetComplete(offset, length); } } // FileManager // void Write(size_t index,unsigned char *buf,size_t length,size_t begin); if (m_filemanager) { m_filemanager -> Write(piece, buf, length, offset); } } void Session::CreateFileManager() { m_filemanager = new FileManager(static_cast(Handler()), m_info_hash); } Piece *Session::GetIncomplete(size_t piece) { for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (p -> GetNumber() == piece) return p; } return NULL; } Piece *Session::GetComplete(size_t piece) { for (piece_v::iterator it = m_complete.begin(); it != m_complete.end(); it++) { Piece *p = *it; if (p -> GetNumber() == piece) return p; } return NULL; } void Session::Verify() { bool repeat; for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (m_filemanager -> Verify(p -> GetNumber(),p -> PieceLength()) ) { for (size_t i = 0; i < p -> PieceLength(); i += p -> SliceSize()) { p -> SetComplete(i, MIN(p -> SliceSize(),p -> PieceLength() - i) ); } } } do { repeat = false; for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (p -> Complete()) { m_complete.push_back(p); p -> ClearComplete(); p -> ClearRequested(); m_incomplete.erase(it); repeat = true; break; } } } while (repeat); } void Session::SendSlice(pSocket *sock,size_t piece,size_t offset,size_t length) { Piece *p = GetComplete(piece); if (p) { unsigned char *buf = new unsigned char[m_piece_length]; m_filemanager -> ReadPiece(piece, buf, m_piece_length ); uint32_t l = htonl(length + 9); sock -> SendBuf( (char *)&l, 4); sock -> Send("\07"); l = htonl(piece); sock -> SendBuf( (char *)&l, 4); l = htonl(offset); sock -> SendBuf( (char *)&l, 4); sock -> SendBuf( (char *)&buf[offset], length); delete buf; p -> SetRequested(offset, length); } } bool Session::SliceSent(size_t piece,size_t offset) { Piece *p = GetComplete(piece); if (p) { if (p -> Requested(offset)) return true; } return false; } void Session::save_piece_v(FILE *fil,piece_v& ref) { size_t q = ref.size(); fwrite(&q, sizeof(size_t), 1, fil); for (piece_v::iterator it = ref.begin(); it != ref.end(); it++) { Piece *p = *it; size_t nr = p -> GetNumber(); fwrite(&nr, sizeof(size_t), 1, fil); nr = p -> PieceLength(); fwrite(&nr, sizeof(size_t), 1, fil); p -> save_slice_m(fil, p -> MapComplete()); p -> save_slice_m(fil, p -> MapRequested()); } } void Session::load_piece_v(FILE *fil,piece_v& ref) { size_t q; fread(&q, sizeof(size_t), 1, fil); while (q--) { size_t nr, piece_length; fread(&nr, sizeof(size_t), 1, fil); fread(&piece_length, sizeof(size_t), 1, fil); Piece *p = new Piece(nr, piece_length); p -> load_slice_m(fil, p -> MapComplete()); p -> load_slice_m(fil, p -> MapRequested()); ref.push_back(p); } } bool Session::GenerateRequest(Peer *peer) { request_v& reqs = peer -> Requests(); size_t piece; size_t offset; size_t length; if (!GetRandomNotRequested(peer, piece, offset, length)) { printf(" *** GetRandomNotRequested failed\n"); return false; // break; // no more unrequested available slices this peer can supply } Request *r = AddRequest(peer, piece, offset, length); if (r) { reqs.push_back(r); } return true; } bool Session::PieceUnique(size_t piece) { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; if (peer -> IsSet(piece)) { return false; } } return true; } void Session::PeerStatus() { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; pSocket *sock = peer -> PeerSocket(); if (sock) { sock -> ShowStatus(m_number_of_pieces); // printf("%20s %5d / %5d\n", peer -> GetIP().c_str(), peer -> GetSet(), m_number_of_pieces); } } } void Session::Update() { PeerHandler& ref = static_cast(Handler()); bool debug_time = (ref.GetDebug() & 512) ? true : false; DEB( Clock ck;) // add connections size_t q = ref.PeerCount(m_info_hash); if (q < ref.GetMinPeers()) { AddConnect(); } DEB( if (debug_time) ck.PrintDiff("1");) // update interested if (m_b_update_interested) { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; pSocket *sock = peer -> PeerSocket(); if (sock && sock -> CTS()) { //printf("Check interest: %s\n", peer -> GetIP().c_str()); bool interested = false; for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (peer -> IsSet(p -> GetNumber())) { interested = true; break; } } if (interested != sock -> Interested()) { sock -> SendInterest(interested); } } // Connected } m_b_update_interested = false; } DEB( if (debug_time) ck.PrintDiff("2");) // make sure all unchoked pSocket's has at least 1 piece OR 256 kB requested data for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; request_v& reqs = peer -> Requests(); // TODO: ignore choke pSocket *sock = peer -> PeerSocket(); // peer -> IsChoked - Choke received from remote end // sock -> Choked - we sent Choke to remote end if (sock && sock -> CTS() && !peer -> IsChoked() ) { size_t ant = GetPieceLength() / SLICE; // size_t n = (ant * 3) / 2; //20; // min number of requests to queue if (reqs.size() < ant / 2) { RequestAvailable(peer); /* if (!GenerateRequest(peer)) { // break; } */ } } else { if (reqs.size()) // unconnected/choked peer has booked requests - remove { while (reqs.size()) { request_v::iterator it = reqs.begin(); Request *r = *it; RemoveRequest(peer, r -> GetPiece(), r -> GetOffset(), r -> GetLength()); delete r; reqs.erase(it); } if (sock && sock -> CTS() && !ref.IgnoreChoke() ) { sock -> SetCloseAndDelete(); } } } } DEB( if (debug_time) ck.PrintDiff("3");) // check for completed pieces if (m_b_check_complete) { for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p = *it; if (p -> Complete()) { //DEB(printf("Found complete piece\n");) if (m_filemanager -> Verify(p -> GetNumber(),p -> PieceLength()) ) { m_complete.push_back(p); ref.SendHave(m_info_hash, p -> GetNumber()); m_incomplete.erase(it); p -> ClearComplete(); p -> ClearRequested(); Save(); break; } else { DEB(printf("\n\n\n *** Verify failed\n\n\n\n");) p -> ClearComplete(); p -> ClearRequested(); } } } m_b_check_complete = false; } DEB( if (debug_time) ck.PrintDiff("4");) // unchoke --- replaced by another choke method further down /* for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; pSocket *sock = peer -> PeerSocket(); if (sock && sock -> CTS()) { if (sock -> Choked() && sock -> ChokeTime() > ref.LocalChokeTime() ) { sock -> SendChoke(false); } } } DEB( if (debug_time) ck.PrintDiff("5");) */ // reset m_complete::requested when all are set /* bool reset = true; for (piece_v::iterator it = m_complete.begin(); it != m_complete.end(); it++) { Piece *p = *it; if (PieceUnique(p -> GetNumber())) { reset = false; break; } } if (reset) { for (piece_v::iterator it = m_complete.begin(); it != m_complete.end(); it++) { Piece *p = *it; p -> ClearRequested(); } } DEB( if (debug_time) ck.PrintDiff("6");) */ // check age of requests if (time(NULL) % 5 == 0) { CheckRequests(); } /* for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; peer -> CheckRequests(); } DEB( if (debug_time) ck.PrintDiff("7");) */ // kick peers with no score if (time(NULL) % 30 == 0) { /* bitmap_t bitmap(m_number_of_pieces); for (piece_v::iterator it = m_complete.begin(); it != m_complete.end(); it++) { Piece *p = *it; bitmap.set(p -> GetNumber()); } for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; pSocket *sock = peer -> PeerSocket(); if (sock) { if (sock -> CTS()) { if (!peer -> Score(&bitmap)) { DEB(printf("Kicking peer with score 0: %s\n", peer -> GetIP().c_str());) sock -> SetCloseAndDelete(); peer -> SetFailed(); } } } } */ double complete = (double)m_complete.size(); double incomplete = (double)m_incomplete.size(); DEB(printf("Progress: %.2f%%\n", complete * 100 / (complete + incomplete));) } DEB( if (debug_time) ck.PrintDiff("9");) // get number of downloaders if (time(NULL) % 5 == 0) { size_t qd = 0; std::vector interested_choked; for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; pSocket *sock = peer -> PeerSocket(); if (sock) { if (peer -> IsInterested() && sock -> Choked()) { interested_choked.push_back(peer); } if (!sock -> Choked()) { qd++; } } } q = interested_choked.size(); if (qd < ref.GetDownloaders() + ref.GetOptimistic() && q > 0) { Peer *peer = interested_choked[random() % q]; pSocket *sock = peer -> PeerSocket(); if (sock) { sock -> SendChoke(false); } } } DEB( if (debug_time) ck.PrintDiff("0");) // calculate up/down speed if (ref.GetDebug() & 4096) { size_t r = 0; size_t w = 0; for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; if (peer) { pSocket *sock = peer -> PeerSocket(); if (sock) { r += sock -> GetBytesR(); w += sock -> GetBytesW(); } } } printf("Down: %d.%03d kB/sec Up: %d.%03d kB/sec\n", r / 1024, r % 1024, w / 1024, w % 1024); } // use OnWriteComplete to send next piece to each pSocket // send "unsent" slices first of all // check for all complete if (!m_incomplete.size()) { DEB(printf("All complete: %s\n", m_info_hash.c_str());) } // kick downloader with lowest d/l rate if (time(NULL) % 30 == 0) { ref.CheckDownloadRate(); } } /* size_t Session::GetInstances(size_t piece) { size_t q = 0; for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *p = *it; pSocket *sock = p -> PeerSocket(); if (sock && sock -> CTS() && p -> IsSet(piece)) { q++; } } return q; } */ void Session::Status(TcpSocket *p) { p -> Send("+---------------------------------------------------------------------
"); p -> Sendf(" Hash : %s
", m_info_hash.c_str()); p -> Sendf(" Announce : %s
", m_announce.c_str()); p -> Sendf(" Name : %s
", m_name.c_str()); p -> Sendf("" "" "" "" "" "" "" "" "" ""); p -> Sendf("", m_files.size()); p -> Sendf("", m_piece_length); p -> Sendf("", m_length); p -> Sendf("", m_number_of_pieces); p -> Sendf("", m_complete.size()); p -> Sendf("", m_last_length); p -> Sendf("", m_pieces.size(), m_pieces.size() / 20); p -> Sendf("
FilesPiece lengthTotal lengthNumber of piecesComplete piecesLast lengthPieces length
%d%lld%lld%d%d%d%d (%d pieces)
"); p -> Send("+---------------------------------------------------------------------
"); std::map mmap; for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end(); it++) { Piece *p0 = *it; size_t q = p0 -> NumberComplete(); if (q) mmap[q].push_back(p0); } piece_v tmp; { for (std::map::iterator it = mmap.begin(); it != mmap.end(); it++) { size_t q = (*it).first; for (piece_v::iterator it = mmap[q].begin(); it != mmap[q].end(); it++) { Piece *p0 = *it; tmp.insert(tmp.begin(), p0); } } } if (tmp.size()) { p -> Sendf("" "" "" "" "" ""); for (piece_v::iterator it = tmp.begin(); it != tmp.end(); it++) { Piece *p0 = *it; size_t q = p0 -> NumberComplete(); size_t req = p0 -> NumberRequested(); size_t avail = Available(p0 -> GetNumber()); if (avail || req) { p -> Sendf("", p0 -> GetNumber(), q, req, avail ); } } p -> Send("
PieceCompleteRequestedAvailability
%d%d%d%d
"); } } size_t Session::Available(int piece) { size_t q = 0; for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; if (peer -> IsSet(piece) && !peer -> IsChoked()) q++; } return q; } void Session::RequestAvailable(Peer *peer) { request_v& reqs = peer -> Requests(); size_t ant = GetPieceLength() / SLICE; int q = (ant * 3) / 2; // requests to add // add requests for most complete if (q > 0) { std::map mmap; for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end() && q > 0; it++) { Piece *p = *it; if (peer -> IsSet(p -> GetNumber()) && !p -> AllRequested()) { mmap[p -> NumberComplete()].push_back(p); } } piece_v tmp; { for (std::map::iterator it = mmap.begin(); it != mmap.end(); it++) { piece_v& ref = (*it).second; for (piece_v::iterator it2 = ref.begin(); it2 != ref.end(); it2++) { Piece *p = *it2; tmp.insert(tmp.begin(), p); } } } { for (piece_v::iterator it = tmp.begin(); it != tmp.end() && q > 0; it++) { Piece *p = *it; int max = 20; while (peer -> IsSet(p -> GetNumber()) && !p -> AllRequested() && max-- && q--) { size_t offset; size_t length; if (p -> GetRandomNotRequested(offset, length)) { Request *r = AddRequest(peer, p -> GetNumber(), offset, length); if (r) { reqs.push_back(r); } } else { printf(" --------> GetRandomNotRequested failed\n"); } } } } } // add requests for least available if (q > 0) { std::map mmap; for (piece_v::iterator it = m_incomplete.begin(); it != m_incomplete.end() && q > 0; it++) { Piece *p = *it; if (peer -> IsSet(p -> GetNumber()) && !p -> AllRequested()) { mmap[Available(p -> GetNumber())].push_back(p); } } piece_v tmp; { for (std::map::iterator it = mmap.begin(); it != mmap.end(); it++) { piece_v& ref = (*it).second; for (piece_v::iterator it2 = ref.begin(); it2 != ref.end(); it2++) { Piece *p = *it2; tmp.push_back(p); } } } { for (piece_v::iterator it = tmp.begin(); it != tmp.end() && q > 0; it++) { Piece *p = *it; int max = 20; while (peer -> IsSet(p -> GetNumber()) && !p -> AllRequested() && max-- && q--) { size_t offset; size_t length; if (p -> GetRandomNotRequested(offset, length)) { Request *r = AddRequest(peer, p -> GetNumber(), offset, length); if (r) { reqs.push_back(r); } } else { printf(" --------> GetRandomNotRequested failed\n"); } } } } } // add random requests if (q > 0) { int max = 20; while (q-- && max--) { GenerateRequest(peer); } } } void Session::RemoveRequests(Peer *peer) { request_v& reqs = peer -> Requests(); while (reqs.size()) { request_v::iterator it = reqs.begin(); Request *r = *it; size_t piece = r -> GetPiece(); size_t offset = r -> GetOffset(); size_t length = r -> GetLength(); RemoveRequest(peer, piece, offset, length); delete r; reqs.erase(it); } } void Session::CheckRequests() { for (peer_v::iterator it = m_peers.begin(); it != m_peers.end(); it++) { Peer *peer = *it; request_v& reqs = peer -> Requests(); for (request_v::iterator it = reqs.begin(); it != reqs.end(); it++) { Request *r = *it; if (r -> Age() > static_cast(Handler()).MaxRequestAge() ) { pSocket *sock = peer -> PeerSocket(); if (sock) sock -> SetCloseAndDelete(); /* size_t piece = r -> GetPiece(); size_t offset = r -> GetOffset(); size_t length = r -> GetLength(); RemoveRequest(peer, piece, offset, length); delete r; reqs.erase(it); break; */ } } } }