SingleDownload.cpp
资源名称:GGBT.rar [点击查看]
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:19k
源码类别:
P2P编程
开发平台:
Visual C++
- // SingleDownload.cpp: implementation of the CSingleDownload class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "testbt.h"
- #include "SingleDownload.h"
- #include "Downloader.h"
- #include "PiecePicker.h"
- #include "StorageWrapper.h"
- #include "Connection.h"
- #include "RateMeasure.h"
- #include "DownloaderFeedback.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- bool bitfield_to_booleans(memstream& membitfield, long l, memstream& memRet);
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CSingleDownload::CSingleDownload(CDownloaderFeedback* pDownloaderFeedback, CDownloader* pDownloader, CConnection* pConnection)
- :m_measure(pDownloader->m_lMaxRatePeriod)
- {
- m_pDownloader = pDownloader;
- m_pConnection = pConnection;
- m_bChoked = true;
- m_bInterested = false;
- m_tLast = 0;
- for (int i=0; i<pDownloader->m_lNumPieces; i++)
- m_vHave.push_back(false);
- // for endgame.
- m_bEndgame = false;
- m_lHave = 0;
- // for feedback
- m_pDownloaderFeedback = pDownloaderFeedback;
- m_pConnection->GetIP(m_lAddr, m_sPort);
- }
- CSingleDownload::~CSingleDownload()
- {
- }
- void CSingleDownload::disconnected()
- {
- if (m_bEndgame)
- {
- // disconnected_end();
- // return ;
- }
- vector<CSingleDownload*>::iterator it =
- find(m_pDownloader->m_vDownloads.begin(), m_pDownloader->m_vDownloads.end(), this);
- assert(it != m_pDownloader->m_vDownloads.end());
- m_pDownloader->m_vDownloads.erase(it);
- for (int i=0; i<m_vHave.size(); i++)
- {
- if (m_vHave[i])
- m_pDownloader->m_pPicker->lost_have(i);
- }
- if (m_bEndgame) return;
- _letgo();
- }
- void CSingleDownload::_letgo()
- {
- vector<long> vHit;
- for (int i=0; i<m_vActiveRequests.size(); i++)
- {
- CRequestsItem& item = m_vActiveRequests[i];
- bool bBefore = m_pDownloader->m_pstrorage->do_I_have_requests(item.m_index);
- m_pDownloader->m_pstrorage->request_lost(item.m_index, item.m_begin, item.m_length);
- if (!bBefore)
- vHit.push_back(item.m_index);
- }
- m_vActiveRequests.erase(m_vActiveRequests.begin(), m_vActiveRequests.end());
- if (vHit.size() > 0)
- {
- for (i=0; i<m_pDownloader->m_vDownloads.size(); i++)
- {
- m_pDownloader->m_vDownloads[i]->_check_interest(vHit);
- m_pDownloader->m_vDownloads[i]->download_more(vHit);
- }
- }
- }
- void CSingleDownload::got_choke()
- {
- if (m_bEndgame)
- {
- got_choke_end();
- return ;
- }
- // ShowMessage(m_pConnection->m_pEConnection, "got_choke()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "got_choke()");
- if (!m_bChoked)
- {
- m_bChoked = true;
- _letgo();
- }
- }
- void CSingleDownload::got_unchoke()
- {
- if (m_bEndgame)
- {
- got_unchoke_end();
- return ;
- }
- // ShowMessage(m_pConnection->m_pEConnection, "got_unchoke()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "got_unchoke()");
- if (m_bChoked)
- {
- m_bChoked = false;
- download_more();
- }
- }
- void CSingleDownload::got_have(long index)
- {
- if (m_bEndgame)
- {
- got_have_end(index);
- return;
- }
- if (m_vHave[index])
- return;
- m_lHave ++;
- assert(m_lHave <= m_vHave.size());
- m_vHave[index] = true;
- m_pDownloader->m_pPicker->got_have(index);
- m_vNewHave.push_back(index);
- vector<long> vHit;
- vHit.push_back(index);
- _check_interest(vHit);
- download_more(vHit);
- char szText[100] = {0};
- sprintf(szText, "got_have() : index = %d, ", index);
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- }
- void CSingleDownload::got_have_bitfield(vector<bool>& vHave)
- {
- if (m_bEndgame)
- {
- got_have_bitfield_end(vHave);
- return;
- }
- assert(vHave.size() == m_pDownloader->m_lNumPieces);
- for (int i=0; i<vHave.size(); i++)
- m_vHave[i] = vHave[i];
- vector<long> vHit;
- for (i=0; i<m_vHave.size(); i++)
- {
- if (m_vHave[i])
- {
- m_pDownloader->m_pPicker->got_have(i);
- m_vNewHave.push_back(i);
- vHit.push_back(i);
- m_lHave++;
- assert(m_lHave <= m_vHave.size());
- }
- }
- _check_interest(vHit);
- download_more();
- // ShowMessage(m_pConnection->m_pEConnection, "got_have_bitfield()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "got_have_bitfield()");
- }
- void CSingleDownload::_check_interest(vector<long>& vHit)
- {
- if (m_bInterested)
- return ;
- for (int i=0; i<vHit.size(); i++)
- {
- long index = vHit[i];
- if (m_vHave[index] && m_pDownloader->m_pstrorage->do_I_have_requests(index))
- {
- m_pConnection->send_interested();
- m_bInterested = true;
- break;
- }
- }
- }
- void CSingleDownload::_lost_interest(vector<long>& vHit)
- {
- if ( (!m_bInterested) || m_vActiveRequests.size() > 0)
- return;
- for (int i=0; i<vHit.size(); i++)
- {
- long index = vHit[i];
- if (m_vHave[index])
- break;
- }
- // can't find
- if (i == vHit.size())
- return;
- for (i=0; i<m_vHave.size(); i++)
- if (m_vHave[i] && m_pDownloader->m_pstrorage->do_I_have_requests(i))
- return;
- m_bInterested = false;
- m_pConnection->send_not_interested();
- }
- void CSingleDownload::download_more( vector<long>& vPieces)
- {
- assert(!m_bEndgame);
- if (m_bChoked || (m_vActiveRequests.size() >= m_pDownloader->m_lBacklog) ||
- m_pConnection->IsPause())
- return;
- if (vPieces.size() <= 0)
- vPieces = m_pDownloader->m_pPicker->GetResult();
- vector<long> vHit;
- _d(vPieces, vHit);
- if (vHit.size() > 0)
- {
- for (int i=0; i<m_pDownloader->m_vDownloads.size(); i++)
- {
- m_pDownloader->m_vDownloads[i]->_lost_interest(vHit);
- }
- }
- }
- void CSingleDownload::_d(vector<long>&vPieces, vector<long>& vHit)
- {
- for (int i=0; i<vPieces.size(); i++)
- {
- long index = vPieces[i];
- if (m_vHave[index])
- {
- while(m_pDownloader->m_pstrorage->do_I_have_requests(index))
- {
- long begin = 0, length = 0;
- m_pDownloader->m_pstrorage->new_request(index, begin, length);
- m_vActiveRequests.push_back(CRequestsItem(index, begin, length));
- m_pConnection->send_request(index, begin, length);
- char szText[100] = {0};
- sprintf(szText, "send request () index = %d, begin = %d, length = %d", index, begin, length);
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- if (!m_pDownloader->m_pstrorage->do_I_have_requests(index))
- vHit.push_back(index);
- if (m_vActiveRequests.size() >= m_pDownloader->m_lBacklog)
- return;
- }
- }
- }
- }
- bool CSingleDownload::got_piece(long index, long begin, memstream& memPiece)
- {
- if (m_bEndgame)
- {
- return got_piece_end(index, begin, memPiece);
- }
- char szText[100] = {0};
- sprintf(szText, "got_piece() : index = %d, begin = %d, length = %d", index, begin, memPiece.size());
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- bool bfind = false;
- for (int i=0; i<m_vActiveRequests.size(); i++)
- {
- CRequestsItem& item = m_vActiveRequests[i];
- if (item.m_index == index && item.m_begin == begin && item.m_length == memPiece.size())
- {
- m_vActiveRequests.erase(m_vActiveRequests.begin() + i);
- bfind = true;
- break;
- }
- }
- if (!bfind)
- {
- // assert(bfind);
- return false;
- }
- time(&m_tLast);
- m_measure.update_rate(memPiece.size());
- m_pDownloader->m_pDownMeasure->update_rate(memPiece.size());
- m_pDownloader->m_pPicker->came_in(index);
- m_pDownloader->m_pstrorage->piece_came_in(index, memPiece, begin, memPiece.size());
- m_pDownloader->m_pRateMeasure->data_came_in(memPiece.size());
- if (m_pDownloader->m_pstrorage->do_I_have(index))
- {
- sprintf(szText, "complete : index = %d", index);
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- m_pDownloader->m_pPicker->complete(index);
- }
- download_more();
- if (m_vActiveRequests.size() <= 0)
- {
- m_bInterested = false;
- m_pConnection->send_not_interested();
- }
- return m_pDownloader->m_pstrorage->do_I_have(index);
- }
- long CSingleDownload::get_rate()
- {
- return m_measure.get_rate();
- }
- long CSingleDownload::get_total()
- {
- return m_measure.get_total();
- }
- bool CSingleDownload::is_snubbed()
- {
- time_t t;
- time(&t);
- if (t < m_tLast)
- {
- assert(false);
- m_tLast = t;
- }
- return ((t - m_tLast) > m_pDownloader->m_lSnubTime);
- }
- bool CSingleDownload::is_choked()
- {
- return m_bChoked;
- }
- bool CSingleDownload::is_interested()
- {
- return m_bInterested;
- }
- float CSingleDownload::GetHaveCountPercent()
- {
- if (m_vHave.size() <= 0)
- {
- assert(false);
- return 0;
- }
- float lPer = (float)m_lHave/m_vHave.size();
- return lPer;
- }
- long CSingleDownload:: get_have_count() const
- {
- return m_vHave.size();
- }
- void CSingleDownload:: get_have(vector<bool>& vHave)
- {
- vHave = m_vHave;
- m_vNewHave.clear();
- }
- void CSingleDownload:: get_new_have(vector<bool>& vHave)
- {
- for (int i=0; i<m_vNewHave.size();i++)
- {
- assert(m_vNewHave[i] < vHave.size());
- vHave[m_vNewHave[i]] = true;
- }
- m_vNewHave.clear();
- }
- //////////////////////////////////////////////////////////////////////////
- // for end game.
- void CSingleDownload::cancel_endgame()
- {
- assert(m_bEndgame);
- m_bEndgame = false;
- m_vActiveRequests.clear();
- }
- void CSingleDownload::make_endgame(vector<CRequestsItem>& vRequests)
- {
- assert(!m_bEndgame);
- m_bEndgame = true;
- for (int i=0; i<m_vActiveRequests.size(); i++)
- vRequests.push_back(m_vActiveRequests[i]);
- m_lHave = 0;
- for (i=0; i<m_vHave.size(); i++)
- if (m_vHave[i])
- m_lHave++;
- // ShowMessage(m_pConnection->m_pEConnection, "***************rnmake_endgame()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "***************rnmake_endgame()");
- }
- void CSingleDownload::mak_endgameflush()
- {
- if (m_bChoked)
- return;
- random_shuffle(m_pDownloader->m_vRequests.begin(), m_pDownloader->m_vRequests.end());
- for (int i=0; i<m_pDownloader->m_vRequests.size(); i++)
- {
- CRequestsItem& item = m_pDownloader->m_vRequests[i];
- bool bfind = false;
- for (int j=0; j<m_vActiveRequests.size(); j++)
- {
- /*if(item.m_index == m_vActiveRequests[j].m_index &&
- item.m_begin == m_vActiveRequests[j].m_begin &&
- item.m_length== m_vActiveRequests[j].m_length)
- //*/
- if (item == m_vActiveRequests[j])
- {
- bfind = true;
- break;
- }
- }
- if (bfind) continue;
- if (m_vHave[item.m_index])
- {
- send_request_end(item.m_index, item.m_begin, item.m_length);
- }
- }
- }
- void CSingleDownload::disconnected_end()
- {
- vector<CSingleDownload*>::iterator it =
- find(m_pDownloader->m_vDownloads.begin(), m_pDownloader->m_vDownloads.end(), this);
- assert(it != m_pDownloader->m_vDownloads.end());
- m_pDownloader->m_vDownloads.erase(it);
- }
- void CSingleDownload::got_unchoke_end()
- {
- // ShowMessage(m_pConnection->m_pEConnection, "got_unchoke_end()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "got_unchoke_end()");
- if (!m_bChoked) return;
- m_bChoked = false;
- if (!m_bInterested) return;
- random_shuffle(m_pDownloader->m_vRequests.begin(), m_pDownloader->m_vRequests.end());
- for (int i=0; i<m_pDownloader->m_vRequests.size(); i++)
- {
- CRequestsItem& item = m_pDownloader->m_vRequests[i];
- if (m_vHave[item.m_index])
- {
- send_request_end(item.m_index, item.m_begin, item.m_length);
- }
- }
- }
- void CSingleDownload::got_choke_end()
- {
- // ShowMessage(m_pConnection->m_pEConnection, "got_choke_end()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "got_choke_end()");
- m_bChoked = true;
- }
- void CSingleDownload::send_request_end(long index, long begin, long length)
- {
- char szText[100] = {0};
- sprintf(szText, "send_request_end() : index = %d, begin = %d, length = %d", index, begin, length);
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- if (!m_bInterested)
- {
- m_bInterested = true;
- m_pConnection->send_interested();
- }
- m_pConnection->send_request(index, begin, length);
- }
- bool CSingleDownload::got_piece_end(long index,long begin, memstream& memPiece)
- {
- char szText[100] = {0};
- sprintf(szText, "got_piece_end() : index = %d, begin = %d, length = %d", index, begin, memPiece.size());
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- bool bfind = false;
- for (int i=0; i<m_pDownloader->m_vRequests.size(); i++)
- {
- CRequestsItem& item = m_pDownloader->m_vRequests[i];
- if (item.m_index == index && item.m_begin == begin && item.m_length == memPiece.size())
- {
- m_pDownloader->m_vRequests.erase(m_pDownloader->m_vRequests.begin() + i);
- bfind = true;
- break;
- }
- }
- if (!bfind)
- return false;
- //*(memPiece + 1) = 30; // test crash the piece to test data_flunk()
- time(&m_tLast);
- m_measure.update_rate(memPiece.size());
- m_pDownloader->m_pDownMeasure->update_rate(memPiece.size());
- m_pDownloader->m_pPicker->came_in(index);
- m_pDownloader->m_pstrorage->piece_came_in(index, memPiece, begin, memPiece.size());
- m_pDownloader->m_pRateMeasure->data_came_in(memPiece.size());
- // piece fail. rerequest.
- if (m_pDownloader->m_pstrorage->do_I_have_requests(index))
- {
- vector<CRequestsItem> vRequests;
- while (m_pDownloader->m_pstrorage->do_I_have_requests(index))
- {
- long begina = 0, lengtha = 0;
- m_pDownloader->m_pstrorage->new_request(index, begina, lengtha);
- vRequests.push_back(CRequestsItem(index, begina, lengtha));
- m_pDownloader->m_vRequests.push_back(CRequestsItem(index, begina, lengtha));
- }
- for (int i=0; i<m_pDownloader->m_vDownloads.size(); i++)
- {
- CSingleDownload* pd = m_pDownloader->m_vDownloads[i];
- if (!pd->is_choked() && pd->m_vHave[index])
- {
- random_shuffle(vRequests.begin(), vRequests.end());
- for (int j=0; j<vRequests.size(); j++)
- {
- // if(pd == this || vRequests[j].m_begin != begin)
- pd->send_request_end(vRequests[j].m_index, vRequests[j].m_begin, vRequests[j].m_length);
- }
- }
- }
- return false;
- }
- // got the fraction of piece. cancel the fraction from other peers.
- for (i=0; i<m_pDownloader->m_vDownloads.size(); i++)
- {
- CSingleDownload* pd = m_pDownloader->m_vDownloads[i];
- pd->SendCancel(index, begin, memPiece.size(), this);
- /*
- if (!pd->is_choked() && pd->m_vHave[index] && pd != this)
- pd->m_pConnection->send_cancel(index, begin, memPiece.size());
- //*/
- }
- // if there are other fractions in requestment, don't send have message.
- for(i=0; i<m_pDownloader->m_vRequests.size(); i++)
- {
- if (m_pDownloader->m_vRequests[i].m_index == index)
- return false;
- }
- // **
- // have completed all the fractions of the piece.
- m_pDownloader->m_pPicker->complete(index);
- sprintf(szText, "complete endgame: index = %d", index);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- // check all the downloads which is waiting for the piece that
- // after the piece was completed, is there still active waiting.
- // if yes break, otherwise make it notinterested.
- for (i=0; i<m_pDownloader->m_vDownloads.size(); i++)
- {
- CSingleDownload* pd = m_pDownloader->m_vDownloads[i];
- if (pd->m_vHave[index])
- {
- bool bStillActive = false;
- for (int j=0; j<m_pDownloader->m_vRequests.size(); j++)
- {
- long lindexa = m_pDownloader->m_vRequests[j].m_index;
- if (pd->m_vHave[lindexa])
- {
- bStillActive = true;
- break;
- }
- }
- if (!bStillActive)
- {
- pd->m_bInterested = false;
- pd->m_pConnection->send_not_interested();
- }
- }
- }
- // check all the downloads, if the the peer of one download completed download then close the connection.
- if (m_pDownloader->m_vRequests.size() <= 0)
- {
- vector<CSingleDownload*> vcopy = m_pDownloader->m_vDownloads;
- for (i=0; i<vcopy.size(); i++)
- {
- if (vcopy[i]->m_lHave >= vcopy[i]->m_vHave.size())
- vcopy[i]->m_pConnection->Close();
- }
- }
- return true;
- }
- void CSingleDownload::got_have_end(long index)
- {
- assert(index >=0 && index <= m_vHave.size());
- if (m_vHave[index])
- return;
- m_vHave[index] = true;
- m_lHave++;
- assert(m_lHave <= m_vHave.size());
- m_pDownloader->m_pPicker->got_have(index);
- m_vNewHave.push_back(index);
- if (m_pDownloader->m_pstrorage->do_I_have(index))
- return;
- // todo:should shuffle here.
- random_shuffle(m_pDownloader->m_vRequests.begin(), m_pDownloader->m_vRequests.end());
- // if the have index is in requrements, then request all the fractions of the have piece.
- for (int i=0; i<m_pDownloader->m_vRequests.size(); i++)
- {
- CRequestsItem& item = m_pDownloader->m_vRequests[i];
- if (item.m_index == index)
- send_request_end(item.m_index, item.m_begin, item.m_length);
- }
- // if download completed, and peer also have all the pieces, then close the connection.
- if (m_pDownloader->m_vRequests.size() <= 0 && m_lHave >= m_vHave.size())
- {
- m_pConnection->Close();
- return;
- }
- char szText[100] = {0};
- sprintf(szText, "got_have_end() : index = %d, ", index);
- // ShowMessage(m_pConnection->m_pEConnection, szText);
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, szText);
- }
- void CSingleDownload::got_have_bitfield_end(vector<bool>& vHave)
- {
- assert(vHave.size() == m_pDownloader->m_lNumPieces);
- m_lHave = 0;
- for (int i=0; i<vHave.size(); i++)
- {
- m_vHave[i] = vHave[i];
- if (m_vHave[i])
- {
- m_lHave ++;
- assert(m_lHave <= m_vHave.size());
- m_pDownloader->m_pPicker->got_have(i);
- m_vNewHave.push_back(i);
- }
- }
- // todo:should shuffle here.
- random_shuffle(m_pDownloader->m_vRequests.begin(), m_pDownloader->m_vRequests.end());
- // if the have index is in requrements, then request all the fractions of the have piece.
- for (i=0; i<m_pDownloader->m_vRequests.size(); i++)
- {
- CRequestsItem& item = m_pDownloader->m_vRequests[i];
- if (m_vHave[item.m_index])
- send_request_end(item.m_index, item.m_begin, item.m_length);
- }
- // if download completed, and peer also have all the pieces, then close the connection.
- if (m_pDownloader->m_vRequests.size() <= 0 && m_lHave >= m_vHave.size())
- m_pConnection->Close();
- // ShowMessage(m_pConnection->m_pEConnection, "got_have_bitfield_end()");
- m_pDownloaderFeedback->ShowSocketMessage(m_lAddr, m_sPort, "got_have_bitfield_end()");
- }
- void CSingleDownload::SendCancel(long index, long begin, long length, CSingleDownload* pOwner)
- {
- for (int i=0; i<m_vActiveRequests.size(); i++)
- {
- CRequestsItem& item = m_vActiveRequests[i];
- if (item.m_index == index &&
- item.m_begin == begin &&
- item.m_length == length)
- {
- m_vActiveRequests.erase(m_vActiveRequests.begin() + i);
- break;
- }
- }
- if (!is_choked() && m_vHave[index] && pOwner!= this)
- m_pConnection->send_cancel(index, begin, length);
- }