📄 baseclient.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"
#ifdef _DEBUG
#include "DebugHelpers.h"
#endif
#include "emule.h"
#include "UpDownClient.h"
#include "FriendList.h"
#include "Clientlist.h"
#include "OtherFunctions.h"
#include "PartFile.h"
#include "ListenSocket.h"
#include "PeerCacheSocket.h"
#include "Friend.h"
#include <zlib/zlib.h>
#include "Packets.h"
#include "Opcodes.h"
#include "SafeFile.h"
#include "Preferences.h"
#include "Server.h"
#include "ClientCredits.h"
#include "IPFilter.h"
#include "Statistics.h"
#include "Version.h"
#include "Sockets.h"
#include "DownloadQueue.h"
#include "UploadQueue.h"
#include "SearchList.h"
#include "SharedFileList.h"
#include "Kademlia/Kademlia/Kademlia.h"
#include "Kademlia/Kademlia/Search.h"
#include "Kademlia/Kademlia/SearchManager.h"
#include "Kademlia/Utils/UInt128.h"
#include "Kademlia/Net/KademliaUDPListener.h"
#include "Kademlia/Kademlia/Prefs.h"
#include "emuledlg.h"
#include "ServerWnd.h"
#include "TransferWnd.h"
#include "ChatWnd.h"
#include "CxImage/xImage.h"
#include "PreviewDlg.h"
#include "Exceptions.h"
#include "Peercachefinder.h"
#include "ClientUDPSocket.h"
#include "shahashset.h"
#include "IP2Country.h" //EastShare - added by AndCycle, IP to Country
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNAMIC(CClientException, CException)
IMPLEMENT_DYNAMIC(CUpDownClient, CObject)
CUpDownClient::CUpDownClient(CClientReqSocket* sender)
{
socket = sender;
reqfile = NULL;
Init();
}
CUpDownClient::CUpDownClient(CPartFile* in_reqfile, uint16 in_port, uint32 in_userid,uint32 in_serverip, uint16 in_serverport, bool ed2kID)
{
//Converting to the HybridID system.. The ED2K system didn't take into account of IP address ending in 0..
//All IP addresses ending in 0 were assumed to be a lowID because of the calculations.
socket = NULL;
reqfile = in_reqfile;
Init();
m_nUserPort = in_port;
//If this is a ED2K source, check if it's a lowID.. If not, convert it to a HyrbidID.
//Else, it's already in hybrid form.
if(ed2kID && !IsLowID(in_userid))
m_nUserIDHybrid = ntohl(in_userid);
else
m_nUserIDHybrid = in_userid;
//If highID and ED2K source, incoming ID and IP are equal..
//If highID and Kad source, incoming IP needs ntohl for the IP
if (!HasLowID() && ed2kID)
m_nConnectIP = in_userid;
else if(!HasLowID())
m_nConnectIP = ntohl(in_userid);
m_dwServerIP = in_serverip;
m_nServerPort = in_serverport;
}
void CUpDownClient::Init()
{
credits = 0;
sumavgUDR = 0; // by BadWolf - Accurate Speed Measurement
m_bAddNextConnect = false; // VQB Fix for LowID slots only on connection
m_nChatstate = MS_NONE;
m_nKadState = KS_NONE;
m_cShowDR = 0;
m_nUDPPort = 0;
m_nKadPort = 0;
m_nTransferedUp = 0;
m_cAsked = 0;
m_cDownAsked = 0;
dataratems = 0;
m_nUpDatarate = 0;
m_pszUsername = 0;
m_structUserCountry = theApp.ip2country->GetDefaultIP2Country(); //EastShare - added by AndCycle, IP to Country
m_nUserIDHybrid = 0;
m_dwServerIP = 0;
m_nServerPort = 0;
m_iFileListRequested = 0;
m_dwLastUpRequest = 0;
m_bEmuleProtocol = false;
m_bCompleteSource = false;
m_bFriendSlot = false;
m_bCommentDirty = false;
m_bReaskPending = false;
m_bUDPPending = false;
m_byEmuleVersion = 0;
m_nUserPort = 0;
m_nPartCount = 0;
m_nUpPartCount = 0;
m_abyPartStatus = 0;
m_abyUpPartStatus = 0;
m_nDownloadState = DS_NONE;
m_dwUploadTime = 0;
m_nTransferedDown = 0;
m_nDownDatarate = 0;
m_nDownDataRateMS = 0;
m_nUploadState = US_NONE;
m_dwLastBlockReceived = 0;
m_byDataCompVer = 0;
m_byUDPVer = 0;
m_bySourceExchangeVer = 0;
m_byAcceptCommentVer = 0;
m_byExtendedRequestsVer = 0;
m_nRemoteQueueRank = 0;
m_dwLastSourceRequest = 0;
m_dwLastSourceAnswer = 0;
m_dwLastAskedForSources = 0;
m_byCompatibleClient = 0;
m_nSourceFrom = SF_SERVER;
m_bIsHybrid = false;
m_bIsML=false;
m_Friend = NULL;
m_uFileRating=0;
(void)m_strFileComment;
m_fMessageFiltered = 0;
m_fIsSpammer = 0;
m_cMessagesReceived = 0;
m_cMessagesSent = 0;
m_nCurSessionUp = 0;
m_nSumForAvgDownDataRate = 0;
m_clientSoft=SO_UNKNOWN;
m_bRemoteQueueFull = false;
md4clr(m_achUserHash);
SetBuddyID(NULL);
m_nBuddyIP = 0;
m_nBuddyPort = 0;
if (socket){
SOCKADDR_IN sockAddr = {0};
int nSockAddrLen = sizeof(sockAddr);
socket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
SetIP(sockAddr.sin_addr.S_un.S_addr);
}
else{
SetIP(0);
}
m_fHashsetRequesting = 0;
m_fSharedDirectories = 0;
m_fSentCancelTransfer = 0;
m_nClientVersion = 0;
m_lastRefreshedDLDisplay = 0;
m_dwDownStartTime = 0;
m_nLastBlockOffset = 0;
m_bUnicodeSupport = false;
m_SecureIdentState = IS_UNAVAILABLE;
m_dwLastSignatureIP = 0;
m_bySupportSecIdent = 0;
m_byInfopacketsReceived = IP_NONE;
m_lastPartAsked = 0xffff;
m_nUpCompleteSourcesCount= 0;
m_fSupportsPreview = 0;
m_fPreviewReqPending = 0;
m_fPreviewAnsPending = 0;
m_bTransferredDownMini = false;
m_addedPayloadQueueSession = 0;
m_nCurQueueSessionPayloadUp = 0; // PENDING: Is this necessary? ResetSessionUp()...
m_lastRefreshedULDisplay = ::GetTickCount();
m_bGPLEvildoer = false;
m_bHelloAnswerPending = false;
m_fNoViewSharedFiles = 0;
m_bMultiPacket = 0;
md4clr(requpfileid);
m_nTotalUDPPackets = 0;
m_nFailedUDPPackets = 0;
m_nUrlStartPos = -1;
m_iHttpSendState = 0;
m_fPeerCache = 0;
m_uPeerCacheDownloadPushId = 0;
m_uPeerCacheUploadPushId = 0;
m_pPCDownSocket = NULL;
m_pPCUpSocket = NULL;
m_uPeerCacheRemoteIP = 0;
m_ePeerCacheDownState = PCDS_NONE;
m_ePeerCacheUpState = PCUS_NONE;
m_bPeerCacheDownHit = false;
m_bPeerCacheUpHit = false;
m_fNeedOurPublicIP = 0;
m_random_update_wait = (uint32)(rand()/(RAND_MAX/1000));
m_bSourceExchangeSwapped = false; // ZZ:DownloadManager
m_dwLastTriedToConnect = ::GetTickCount()-20*60*1000; // ZZ:DownloadManager
m_fQueueRankPending = 0;
m_fUnaskQueueRankRecv = 0;
m_fFailedFileIdReqs = 0;
m_slotNumber = 0;
lastSwapForSourceExchangeTick = 0;
m_pReqFileAICHHash = NULL;
m_fSupportsAICH = 0;
m_fAICHRequested = 0;
}
CUpDownClient::~CUpDownClient(){
if (IsAICHReqPending()){
m_fAICHRequested = FALSE;
CAICHHashSet::ClientAICHRequestFailed(this);
}
theApp.clientlist->RemoveClient(this, _T("Destructing client object"));
if (m_Friend){
m_Friend->SetLinkedClient(NULL);
}
if (socket){
socket->client = 0;
socket->Safe_Delete();
}
if (m_pPCDownSocket){
m_pPCDownSocket->client = NULL;
m_pPCDownSocket->Safe_Delete();
}
if (m_pPCUpSocket){
m_pPCUpSocket->client = NULL;
m_pPCUpSocket->Safe_Delete();
}
if (m_pszUsername)
free(m_pszUsername);
if (m_abyPartStatus){
delete[] m_abyPartStatus;
m_abyPartStatus = NULL;
}
if (m_abyUpPartStatus){
delete[] m_abyUpPartStatus;
m_abyUpPartStatus = NULL;
}
ClearUploadBlockRequests();
for (POSITION pos = m_DownloadBlocks_list.GetHeadPosition();pos != 0;)
delete m_DownloadBlocks_list.GetNext(pos);
for (POSITION pos = m_RequestedFiles_list.GetHeadPosition();pos != 0;)
delete m_RequestedFiles_list.GetNext(pos);
for (POSITION pos = m_PendingBlocks_list.GetHeadPosition();pos != 0;){
Pending_Block_Struct *pending = m_PendingBlocks_list.GetNext(pos);
delete pending->block;
// Not always allocated
if (pending->zStream){
inflateEnd(pending->zStream);
delete pending->zStream;
}
delete pending;
}
for (POSITION pos = m_WaitingPackets_list.GetHeadPosition();pos != 0;)
delete m_WaitingPackets_list.GetNext(pos);
DEBUG_ONLY (theApp.listensocket->Debug_ClientDeleted(this));
SetUploadFileID(NULL);
m_fileReaskTimes.RemoveAll(); // ZZ:DownloadManager (one resk timestamp for each file)
if (m_pReqFileAICHHash != NULL)
delete m_pReqFileAICHHash;
}
void CUpDownClient::ClearHelloProperties()
{
m_nUDPPort = 0;
m_byUDPVer = 0;
m_byDataCompVer = 0;
m_byEmuleVersion = 0;
m_bySourceExchangeVer = 0;
m_byAcceptCommentVer = 0;
m_byExtendedRequestsVer = 0;
m_byCompatibleClient = 0;
m_nKadPort = 0;
m_bySupportSecIdent = 0;
m_fSupportsPreview = 0;
m_nClientVersion = 0;
m_fSharedDirectories = 0;
m_bMultiPacket = 0;
m_fPeerCache = 0;
m_uPeerCacheDownloadPushId = 0;
m_uPeerCacheUploadPushId = 0;
}
bool CUpDownClient::ProcessHelloPacket(char* pachPacket, uint32 nSize){
CSafeMemFile data((BYTE*)pachPacket,nSize);
data.ReadUInt8(); // read size of userhash
// reset all client properties; a client may not send a particular emule tag any longer
ClearHelloProperties();
return ProcessHelloTypePacket(&data);
}
bool CUpDownClient::ProcessHelloAnswer(char* pachPacket, uint32 nSize)
{
CSafeMemFile data((BYTE*)pachPacket,nSize);
bool bIsMule = ProcessHelloTypePacket(&data);
m_bHelloAnswerPending = false;
return bIsMule;
}
bool CUpDownClient::ProcessHelloTypePacket(CSafeMemFile* data)
{
bool bDbgInfo = thePrefs.GetUseDebugDevice();
m_strHelloInfo.Empty();
// clear hello properties which can be changed _only_ on receiving OP_Hello/OP_HelloAnswer
m_bIsHybrid = false;
m_bIsML = false;
m_fNoViewSharedFiles = 0;
m_bUnicodeSupport = false;
data->ReadHash16(m_achUserHash);
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T("Hash=%s (%s)"), md4str(m_achUserHash), DbgGetHashTypeString(m_achUserHash));
m_nUserIDHybrid = data->ReadUInt32();
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" UserID=%u (%s)"), m_nUserIDHybrid, ipstr(m_nUserIDHybrid));
uint16 nUserPort = data->ReadUInt16(); // hmm clientport is sent twice - why?
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" Port=%u"), nUserPort);
DWORD dwEmuleTags = 0;
uint32 tagcount = data->ReadUInt32();
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" Tags=%u"), tagcount);
for (uint32 i = 0;i < tagcount; i++){
CTag temptag(data, true);
updateScoreAdjustor(); //VeryCD
switch (temptag.GetNameID()){
case CT_NAME:
if (m_pszUsername){
free(m_pszUsername);
m_pszUsername = NULL; // needed, in case 'nstrdup' fires an exception!!
}
m_pszUsername = _tcsdup(temptag.GetStr());
if (bDbgInfo){
if (m_pszUsername){//filter username for bad chars
TCHAR* psz = m_pszUsername;
while (*psz != _T('\0')) {
if (*psz == _T('\n') || *psz == _T('\r'))
*psz = _T(' ');
psz++;
}
}
m_strHelloInfo.AppendFormat(_T("\n Name='%s'"), m_pszUsername);
}
break;
case CT_VERSION:
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T("\n Version=%u"), temptag.GetInt());
m_nClientVersion = temptag.GetInt();
break;
case CT_PORT:
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T("\n Port=%u"), temptag.GetInt());
nUserPort = temptag.GetInt();
break;
case CT_MOD_VERSION:
if (temptag.IsStr())
m_strModVersion = temptag.GetStr();
else if (temptag.IsInt())
m_strModVersion.Format(_T("ModID=%u"), temptag.GetInt());
else
m_strModVersion = _T("ModID=<Unknwon>");
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T("\n ModID=%s"), m_strModVersion);
CheckForGPLEvilDoer();
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -