📄 uploadclient.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//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., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include <zlib/zlib.h>
#include "UpDownClient.h"
#include "UrlClient.h"
#include "Opcodes.h"
#include "Packets.h"
#include "UploadQueue.h"
#include "Statistics.h"
#include "ClientList.h"
#include "ClientUDPSocket.h"
#include "SharedFileList.h"
#include "KnownFileList.h"
#include "PartFile.h"
#include "ClientCredits.h"
#include "ListenSocket.h"
#include "PeerCacheSocket.h"
#include "Sockets.h"
#include "OtherFunctions.h"
#include "SafeFile.h"
#include "DownloadQueue.h"
#include "emuledlg.h"
#include "TransferWnd.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// members of CUpDownClient
// which are mainly used for uploading functions
CBarShader CUpDownClient::s_UpStatusBar(16);
void CUpDownClient::DrawUpStatusBar(CDC* dc, RECT* rect, bool onlygreyrect, bool bFlat) const
{
COLORREF crNeither;
COLORREF crNextSending;
COLORREF crBoth;
COLORREF crSending;
if(GetSlotNumber() <= theApp.uploadqueue->GetActiveUploadsCount() ||
(GetUploadState() != US_UPLOADING && GetUploadState() != US_CONNECTING) ) {
crNeither = RGB(224, 224, 224);
crNextSending = RGB(255,208,0);
crBoth = bFlat ? RGB(0, 0, 0) : RGB(104, 104, 104);
crSending = RGB(0, 150, 0);
} else {
// grayed out
crNeither = RGB(248, 248, 248);
crNextSending = RGB(255,244,191);
crBoth = bFlat ? RGB(191, 191, 191) : RGB(191, 191, 191);
crSending = RGB(191, 229, 191);
}
// wistily: UpStatusFix
CKnownFile* currequpfile = theApp.sharedfiles->GetFileByID(requpfileid);
uint32 filesize;
if (currequpfile)
filesize=currequpfile->GetFileSize();
else
filesize=PARTSIZE*m_nUpPartCount;
// wistily: UpStatusFix
if(filesize > 0) {
s_UpStatusBar.SetFileSize(filesize);
s_UpStatusBar.SetHeight(rect->bottom - rect->top);
s_UpStatusBar.SetWidth(rect->right - rect->left);
s_UpStatusBar.Fill(crNeither);
if (!onlygreyrect && m_abyUpPartStatus) {
for (uint32 i = 0;i < m_nUpPartCount;i++)
if(m_abyUpPartStatus[i])
s_UpStatusBar.FillRange(PARTSIZE*(i),PARTSIZE*(i+1),crBoth);
}
const Requested_Block_Struct* block;
if (!m_BlockRequests_queue.IsEmpty()){
block = m_BlockRequests_queue.GetHead();
if(block){
uint32 start = block->StartOffset/PARTSIZE;
s_UpStatusBar.FillRange(start*PARTSIZE, (start+1)*PARTSIZE, crNextSending);
}
}
if (!m_DoneBlocks_list.IsEmpty()){
block = m_DoneBlocks_list.GetTail();
if(block){
uint32 start = block->StartOffset/PARTSIZE;
s_UpStatusBar.FillRange(start*PARTSIZE, (start+1)*PARTSIZE, crNextSending);
}
}
if (!m_DoneBlocks_list.IsEmpty()){
for(POSITION pos=m_DoneBlocks_list.GetHeadPosition();pos!=0;){
block = m_DoneBlocks_list.GetNext(pos);
s_UpStatusBar.FillRange(block->StartOffset, block->EndOffset + 1, crSending);
}
}
s_UpStatusBar.Draw(dc, rect->left, rect->top, bFlat);
}
}
void CUpDownClient::SetUploadState(EUploadState news){
// don't add any final cleanups for US_NONE here
m_nUploadState = news;
theApp.emuledlg->transferwnd->clientlistctrl.RefreshClient(this);
}
/**
* Gets the queue score multiplier for this client, taking into consideration client's credits
* and the requested file's priority.
*/
float CUpDownClient::GetCombinedFilePrioAndCredit() {
if (credits == 0){
ASSERT ( IsKindOf(RUNTIME_CLASS(CUrlClient)) );
return 0;
}
return (uint32)(10.0f*credits->GetScoreRatio(GetIP())*float(GetFilePrioAsNumber()));
}
/**
* Gets the file multiplier for the file this client has requested.
*/
int CUpDownClient::GetFilePrioAsNumber() const {
CKnownFile* currequpfile = theApp.sharedfiles->GetFileByID(requpfileid);
if(!currequpfile)
return 0;
// TODO coded by tecxx & herbert, one yet unsolved problem here:
// sometimes a client asks for 2 files and there is no way to decide, which file the
// client finally gets. so it could happen that he is queued first because of a
// high prio file, but then asks for something completely different.
int filepriority = 10; // standard
switch(currequpfile->GetUpPriority()){
case PR_VERYHIGH:
filepriority = 18;
break;
case PR_HIGH:
filepriority = 9;
break;
case PR_LOW:
filepriority = 6;
break;
case PR_VERYLOW:
filepriority = 2;
break;
case PR_NORMAL:
default:
filepriority = 7;
break;
}
return filepriority;
}
/**
* Gets the current waiting score for this client, taking into consideration waiting
* time, priority of requested file, and the client's credits.
*/
uint32 CUpDownClient::GetScore(bool sysvalue, bool isdownloading, bool onlybasevalue) const
{
if (!m_pszUsername)
return 0;
if (credits == 0){
ASSERT ( IsKindOf(RUNTIME_CLASS(CUrlClient)) );
return 0;
}
CKnownFile* currequpfile = theApp.sharedfiles->GetFileByID(requpfileid);
if(!currequpfile)
return 0;
// bad clients (see note in function)
if (credits->GetCurrentIdentState(GetIP()) == IS_IDBADGUY)
return 0;
// friend slot
if (IsFriend() && GetFriendSlot() && !HasLowID())
return 0x0FFFFFFF;
if (IsBanned() || m_bGPLEvildoer)
return 0;
if (sysvalue && HasLowID() && !(socket && socket->IsConnected())){
return 0;
}
int filepriority = GetFilePrioAsNumber();
// calculate score, based on waitingtime and other factors
float fBaseValue;
if (onlybasevalue)
fBaseValue = 10000;
else if (!isdownloading)
fBaseValue = (float)(::GetTickCount()-GetWaitStartTime())/1000;
else{
// we dont want one client to download forever
// the first 15 min downloadtime counts as 15 min waitingtime and you get a 15 min bonus while you are in the first 15 min :)
// (to avoid 20 sec downloads) after this the score won't raise anymore
fBaseValue = (float)(m_dwUploadTime-GetWaitStartTime());
ASSERT ( m_dwUploadTime-GetWaitStartTime() >= 0 ); //oct 28, 02: changed this from "> 0" to ">= 0"
fBaseValue += (float)(::GetTickCount() - m_dwUploadTime > 900000)? 900000:1800000;
fBaseValue /= 1000;
}
//VeryCD版,积分调整
//if( thePrefs.GetCHNScore() &&
// (strstr(this->GetUserName(), "[CHN]") || (strstr(this->GetUserName(), "[VeryCD]") ||
// (thePrefs.UseCreditSystem() && credits->GetScoreRatio(GetIP())!=1) ||
// (currequpfile->GetUpPriority() == PR_VERYHIGH) ||
// (IsEmuleClient() && (GetAvailablePartCount() > 0) || (m_nDownloadState == DS_DOWNLOADING))||
// IsFriend())
// )
//)
//{
// fBaseValue += thePrefs.GetCHNScore();
//}
//if (IsFriend()) {
// fBaseValue *= 2;
//}
//if (IsEmuleClient() && GetAvailablePartCount() > 0) {
// fBaseValue *= 1.2;
//}
//if (IsEmuleClient() && m_nDownloadState == DS_DOWNLOADING) {
// fBaseValue *= 1.5;
//}
//VeryCD版,积分调整结束
for (POSITION pos = scoreAdjustor.GetHeadPosition();pos != 0; ){
sint64 b = scoreAdjustor.GetNext(pos);
switch (b >> 56) {
case 0:
fBaseValue += b & 0xFFFFFFFFFFFFFF;
break;
case 1:
fBaseValue -= b & 0xFFFFFFFFFFFFFF;
break;
case 2:
fBaseValue *= b & 0xFFFFFFFFFFFFFF;
break;
case 3:
fBaseValue /= b & 0xFFFFFFFFFFFFFF;
break;
}
}
if(thePrefs.UseCreditSystem())
{
float modif = credits->GetScoreRatio(GetIP());
fBaseValue *= modif;
}
if (!onlybasevalue)
fBaseValue *= (float(filepriority)/10.0f);
if( (IsEmuleClient() || this->GetClientSoft() < 10) && m_byEmuleVersion <= 0x19 )
fBaseValue *= 0.5f;
return (uint32)fBaseValue;
}
class CSyncHelper
{
public:
CSyncHelper()
{
m_pObject = NULL;
}
~CSyncHelper()
{
if (m_pObject)
m_pObject->Unlock();
}
CSyncObject* m_pObject;
};
void CUpDownClient::CreateNextBlockPackage(){
// See if we can do an early return. There may be no new blocks to load from disk and add to buffer, or buffer may be large enough allready.
if(m_BlockRequests_queue.IsEmpty() || // There are no new blocks requested
m_addedPayloadQueueSession > GetQueueSessionPayloadUp() && m_addedPayloadQueueSession-GetQueueSessionPayloadUp() > 50*1024) { // the buffered data is large enough allready
return;
}
CFile file;
byte* filedata = 0;
CString fullname;
bool bFromPF = true; // Statistic to breakdown uploaded data by complete file vs. partfile.
CSyncHelper lockFile;
try{
// Buffer new data if current buffer is less than 1 MBytes
while (!m_BlockRequests_queue.IsEmpty() &&
(m_addedPayloadQueueSession <= GetQueueSessionPayloadUp() || m_addedPayloadQueueSession-GetQueueSessionPayloadUp() < 100*1024)) {
Requested_Block_Struct* currentblock = m_BlockRequests_queue.GetHead();
CKnownFile* srcfile = theApp.sharedfiles->GetFileByID(currentblock->FileID);
if (!srcfile)
throw GetResString(IDS_ERR_REQ_FNF);
if (srcfile->IsPartFile() && ((CPartFile*)srcfile)->GetStatus() != PS_COMPLETE){
// Do not access a part file, if it is currently moved into the incoming directory.
// Because the moving of part file into the incoming directory may take a noticable
// amount of time, we can not wait for 'm_FileCompleteMutex' and block the main thread.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -