📄 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 "Log.h"
#include "IP2Country.h" //EastShare - added by AndCycle, IP to Country
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//EastShare Start - added by AndCycle, IP to Country
// Superlexx - client's location
CString CUpDownClient::GetCountryName(bool longName) const {
//display in client detail
if(longName && theApp.ip2country->IsIP2Country() == false) return GetResString(IDS_DISABLED);
if(theApp.ip2country->IsIP2Country() == false) return _T("");
if(longName) return m_structUserCountry->LongCountryName;
CString tempStr;
switch(thePrefs.GetIP2CountryNameMode()){
case IP2CountryName_SHORT:
// EastShare - Modified by Pretender
// tempStr.Format("<%s>",m_structUserCountry->ShortCountryName);
tempStr.Format(_T("%s: "),m_structUserCountry->ShortCountryName);
return tempStr;
case IP2CountryName_MID:
// tempStr.Format("<%s>",m_structUserCountry->MidCountryName);
tempStr.Format(_T("%s: "),m_structUserCountry->MidCountryName);
return tempStr;
case IP2CountryName_LONG:
// tempStr.Format("<%s>",m_structUserCountry->LongCountryName);
tempStr.Format(_T("%s: "),m_structUserCountry->LongCountryName);
return tempStr;
// EastShare - Modified by Pretender
}
return _T("");
}
int CUpDownClient::GetCountryFlagIndex() const {
return m_structUserCountry->FlagIndex;
}
void CUpDownClient::ResetIP2Country(){
m_structUserCountry = theApp.ip2country->GetCountryFromIP(m_dwUserIP);
}
//EastShare End - added by AndCycle, IP to Country
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()
{
m_structUserCountry = theApp.ip2country->GetDefaultIP2Country(); //EastShare - added by AndCycle, IP to Country
credits = 0;
m_nSumForAvgUpDataRate = 0;
m_bAddNextConnect = false;
m_nChatstate = MS_NONE;
m_nKadState = KS_NONE;
m_cShowDR = 0;
m_nUDPPort = 0;
m_nKadPort = 0;
m_nTransferredUp = 0;
m_cAsked = 0;
m_cDownAsked = 0;
m_nUpDatarate = 0;
m_pszUsername = 0;
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_nTransferredDown = 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_nCurSessionDown = 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);
//EastShare Start - added by AndCycle, IP to Country
if(m_nConnectIP != m_dwUserIP){
m_structUserCountry = theApp.ip2country->GetCountryFromIP(m_dwUserIP);
}
//EastShare End - added by AndCycle, IP to Country
}
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 = (UINT)-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;
m_byKadVersion = 0;
SetLastBuddyPingPongTime();
m_fSentOutOfPartReqs = 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;
m_byKadVersion = 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -