📄 baseclient.cpp
字号:
{
data->WriteHash16(thePrefs.GetUserHash());
uint32 clientid;
clientid = theApp.GetID();
data->WriteUInt32(clientid);
data->WriteUInt16(thePrefs.GetPort());
uint32 tagcount = 5;
if( m_nBuddyIP && m_nBuddyPort )
tagcount += 2;
data->WriteUInt32(tagcount);
// eD2K Name
// TODO implement multi language website which informs users of the effects of bad mods
CTag tagName(CT_NAME, (!m_bGPLEvildoer) ? thePrefs.GetUserNick() : _T("Please use a GPL-conform version of eMule") );
tagName.WriteTagToFile(data, utf8strRaw);
// eD2K Version
CTag tagVersion(CT_VERSION,EDONKEYVERSION);
tagVersion.WriteTagToFile(data);
// eMule UDP Ports
uint32 kadUDPPort = 0;
if(Kademlia::CKademlia::isConnected())
{
kadUDPPort = thePrefs.GetUDPPort();
}
CTag tagUdpPorts(CT_EMULE_UDPPORTS,
((uint32)kadUDPPort << 16) |
((uint32)thePrefs.GetUDPPort() ) );
tagUdpPorts.WriteTagToFile(data);
if( m_nBuddyPort && m_nBuddyIP )
{
CTag tagBuddyIP(CT_EMULE_BUDDYIP, m_nBuddyIP );
tagBuddyIP.WriteTagToFile(data);
CTag tagBuddyPort(CT_EMULE_BUDDYUDP,
((uint32)m_nBuddyPort ) );
tagBuddyPort.WriteTagToFile(data);
}
// eMule Misc. Options #1
const UINT uUdpVer = 4;
const UINT uDataCompVer = 1;
const UINT uSupportSecIdent = theApp.clientcredits->CryptoAvailable() ? 3 : 0;
const UINT uSourceExchangeVer = 3;
const UINT uExtendedRequestsVer = 2;
const UINT uAcceptCommentVer = 1;
const UINT uNoViewSharedFiles = (thePrefs.CanSeeShares() == vsfaNobody) ? 1 : 0; // for backward compatibility this has to be a 'negative' flag
const UINT uMultiPacket = 1;
const UINT uSupportPreview = (thePrefs.CanSeeShares() != vsfaNobody) ? 1 : 0; // set 'Preview supported' only if 'View Shared Files' allowed
const UINT uPeerCache = 1;
#ifdef _UNICODE
const UINT uUnicodeSupport = 1;
#else
const UINT uUnicodeSupport = 0;
#endif
const UINT nAICHVer = 1;
CTag tagMisOptions(CT_EMULE_MISCOPTIONS1,
(nAICHVer << ((4*7)+1)) |
(uUnicodeSupport << 4*7) |
(uUdpVer << 4*6) |
(uDataCompVer << 4*5) |
(uSupportSecIdent << 4*4) |
(uSourceExchangeVer << 4*3) |
(uExtendedRequestsVer << 4*2) |
(uAcceptCommentVer << 4*1) |
(uPeerCache << 1*3) |
(uNoViewSharedFiles << 1*2) |
(uMultiPacket << 1*1) |
(uSupportPreview << 1*0) );
tagMisOptions.WriteTagToFile(data);
// eMule Version
CTag tagMuleVersion(CT_EMULE_VERSION,
//(uCompatibleClientID << 24) |
(VERSION_MJR << 17) |
(VERSION_MIN << 10) |
(VERSION_UPDATE << 7) //|
// (RESERVED )
);
tagMuleVersion.WriteTagToFile(data);
uint32 dwIP;
uint16 nPort;
if (theApp.serverconnect->IsConnected()){
dwIP = theApp.serverconnect->GetCurrentServer()->GetIP();
nPort = theApp.serverconnect->GetCurrentServer()->GetPort();
#ifdef _DEBUG
if (dwIP == theApp.serverconnect->GetLocalIP()){
dwIP = 0;
nPort = 0;
}
#endif
}
else{
nPort = 0;
dwIP = 0;
}
data->WriteUInt32(dwIP);
data->WriteUInt16(nPort);
// data->WriteUInt32(dwIP); //The Hybrid added some bits here, what ARE THEY FOR?
}
void CUpDownClient::ProcessMuleCommentPacket(char* pachPacket, uint32 nSize)
{
if (reqfile && reqfile->IsPartFile())
{
CSafeMemFile data((BYTE*)pachPacket, nSize);
uint8 uRating = data.ReadUInt8();
if (thePrefs.GetLogRatingDescReceived() && uRating > 0)
AddDebugLogLine(false, GetResString(IDS_RATINGRECV), m_strClientFilename, uRating);
UINT uLength = data.ReadUInt32();
if (uLength > 0)
{
// we have to increase the raw max. allowed file comment len because of possible UTF8 encoding.
if (uLength > MAXFILECOMMENTLEN*3)
uLength = MAXFILECOMMENTLEN*3;
CString strComment = data.ReadString(GetUnicodeSupport(), uLength);
if (thePrefs.GetLogRatingDescReceived() && !strComment.IsEmpty())
AddDebugLogLine(false, GetResString(IDS_DESCRIPTIONRECV), m_strClientFilename, strComment);
// test if comment is filtered
if (!thePrefs.GetCommentFilter().IsEmpty())
{
CString strCommentLower(strComment);
strCommentLower.MakeLower();
int iPos = 0;
CString strFilter(thePrefs.GetCommentFilter().Tokenize(_T("|"), iPos));
while (!strFilter.IsEmpty())
{
// comment filters are already in lowercase, compare with temp. lowercased received comment
if (strCommentLower.Find(strFilter) >= 0)
{
strComment.Empty();
uRating = 0;
break;
}
strFilter = thePrefs.GetCommentFilter().Tokenize(_T("|"), iPos);
}
}
if (!strComment.IsEmpty() || uRating > 0)
{
m_strFileComment = strComment;
m_uFileRating = uRating;
reqfile->UpdateFileRatingCommentAvail();
}
}
}
}
bool CUpDownClient::Disconnected(LPCTSTR pszReason, bool bFromSocket){
//If this is a KAD client object, just delete it!
ASSERT(theApp.clientlist->IsValidClient(this));
SetKadState(KS_NONE);
if (GetUploadState() == US_UPLOADING || GetUploadState() == US_CONNECTING)
theApp.uploadqueue->RemoveFromUploadQueue(this, pszReason);
// 28-Jun-2004 [bc]: re-applied this patch which was in 0.30b-0.30e. it does not seem to solve the bug but
// it does not hurt either...
if (m_BlockRequests_queue.GetCount() > 0 || m_DoneBlocks_list.GetCount()){
// Although this should not happen, it seems(?) to happens sometimes. The problem we may run into here is as follows:
//
// 1.) If we do not clear the block send requests for that client, we will send those blocks next time the client
// gets an upload slot. But because we are starting to send any available block send requests right _before_ the
// remote client had a chance to prepare to deal with them, the first sent blocks will get dropped by the client.
// Worst thing here is, because the blocks are zipped and can therefore only be uncompressed when the first block
// was received, all of those sent blocks will create a lot of uncompress errors at the remote client.
//
// 2.) The remote client may have already received those blocks from some other client when it gets the next
// upload slot.
AddDebugLogLine(DLP_LOW, false, _T("***NOTE: Disconnected client with non empty block send queue; %s reqs: %s doneblocks: %s"), DbgGetClientInfo(), m_BlockRequests_queue.GetCount() > 0 ? _T("true") : _T("false"), m_DoneBlocks_list.GetCount() ? _T("true") : _T("false"));
ClearUploadBlockRequests();
}
if (GetDownloadState() == DS_DOWNLOADING){
if (m_ePeerCacheDownState == PCDS_WAIT_CACHE_REPLY || m_ePeerCacheDownState == PCDS_DOWNLOADING)
theApp.m_pPeerCache->DownloadAttemptFailed();
if (thePrefs.GetLogUlDlEvents())
AddDebugLogLine(DLP_VERYLOW, false,_T("Download session ended. User: %s Reason: %s"), GetUserName(), pszReason);
SetDownloadState(DS_ONQUEUE);
}
else{
// ensure that all possible block requests are removed from the partfile
ClearDownloadBlockRequests();
}
// we had still an AICH request pending, handle it
if (IsAICHReqPending()){
m_fAICHRequested = FALSE;
CAICHHashSet::ClientAICHRequestFailed(this);
}
// The remote client does not have to answer with OP_HASHSETANSWER *immediatly*
// after we've sent OP_HASHSETREQUEST. It may occure that a (buggy) remote client
// is sending use another OP_FILESTATUS which would let us change to DL-state to DS_ONQUEUE.
if (((GetDownloadState() == DS_REQHASHSET) || m_fHashsetRequesting) && (reqfile))
reqfile->hashsetneeded = true;
ASSERT(theApp.clientlist->IsValidClient(this));
//check if this client is needed in any way, if not delete it
bool bDelete = true;
switch(m_nUploadState){
case US_ONUPLOADQUEUE:
bDelete = false;
break;
};
switch(m_nDownloadState){
case DS_ONQUEUE:
case DS_TOOMANYCONNS:
case DS_NONEEDEDPARTS:
case DS_LOWTOLOWIP:
bDelete = false;
};
switch(m_nUploadState){
case US_CONNECTING:
if (thePrefs.GetLogUlDlEvents())
AddDebugLogLine(DLP_VERYLOW, true,_T("---- %s: Removing connecting client from upload list. Reason: %s ----"), DbgGetClientInfo(), pszReason);
case US_WAITCALLBACK:
case US_ERROR:
theApp.clientlist->m_globDeadSourceList.AddDeadSource(this);
bDelete = true;
};
switch(m_nDownloadState){
case DS_CONNECTING:
case DS_WAITCALLBACK:
case DS_ERROR:
theApp.clientlist->m_globDeadSourceList.AddDeadSource(this);
bDelete = true;
};
if (GetChatState() != MS_NONE){
bDelete = false;
theApp.emuledlg->chatwnd->chatselector.ConnectingResult(this,false);
}
if (!bFromSocket && socket){
ASSERT (theApp.listensocket->IsValidSocket(socket));
socket->Safe_Delete();
}
socket = 0;
if (m_iFileListRequested){
AddLogLine(true,GetResString(IDS_SHAREDFILES_FAILED),GetUserName());
m_iFileListRequested = 0;
}
if (m_Friend)
theApp.friendlist->RefreshFriend(m_Friend);
theApp.emuledlg->transferwnd->clientlistctrl.RefreshClient(this);
if (bDelete){
if (thePrefs.GetDebugClientTCPLevel() > 0)
Debug(_T("--- Deleted client %s; Reason=%s\n"), DbgGetClientInfo(true), pszReason);
return true;
}
else{
if (thePrefs.GetDebugClientTCPLevel() > 0)
Debug(_T("--- Disconnected client %s; Reason=%s\n"), DbgGetClientInfo(true), pszReason);
m_fHashsetRequesting = 0;
SetSentCancelTransfer(0);
m_bHelloAnswerPending = false;
m_fQueueRankPending = 0;
m_fFailedFileIdReqs = 0;
m_fUnaskQueueRankRecv = 0;
m_uPeerCacheDownloadPushId = 0;
m_uPeerCacheUploadPushId = 0;
m_uPeerCacheRemoteIP = 0;
SetPeerCacheDownState(PCDS_NONE);
SetPeerCacheUpState(PCUS_NONE);
if (m_pPCDownSocket){
m_pPCDownSocket->client = NULL;
m_pPCDownSocket->Safe_Delete();
}
if (m_pPCUpSocket){
m_pPCUpSocket->client = NULL;
m_pPCUpSocket->Safe_Delete();
}
return false;
}
}
//Returned bool is not if the TryToConnect is successful or not..
//false means the client was deleted!
//true means the client was not deleted!
bool CUpDownClient::TryToConnect(bool bIgnoreMaxCon, CRuntimeClass* pClassSocket)
{
if (theApp.listensocket->TooManySockets() && !bIgnoreMaxCon && !(socket && socket->IsConnected()))
{
if(Disconnected(_T("Too many connections")))
{
delete this;
return false;
}
return true;
}
uint32 uClientIP = GetIP();
if (uClientIP == 0 && !HasLowID())
uClientIP = ntohl(m_nUserIDHybrid);
if (uClientIP)
{
// although we filter all received IPs (server sources, source exchange) and all incomming connection attempts,
// we do have to filter outgoing connection attempts here too, because we may have updated the ip filter list
if (theApp.ipfilter->IsFiltered(uClientIP))
{
theStats.filteredclients++;
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(true, GetResString(IDS_IPFILTERED), ipstr(uClientIP), theApp.ipfilter->GetLastHit());
if (Disconnected(_T("IPFilter")))
{
delete this;
return false;
}
return true;
}
// for safety: check again whether that IP is banned
if (theApp.clientlist->IsBannedClient(uClientIP))
{
if (thePrefs.GetLogBannedClients())
AddDebugLogLine(false, _T("Refused to connect to banned client %s"), DbgGetClientInfo());
if (Disconnected(_T("Banned IP")))
{
delete this;
return false;
}
return true;
}
}
if( GetKadState() == KS_QUEUED_FWCHECK )
SetKadState(KS_CONNECTING_FWCHECK);
if ( HasLowID() )
{
if(!theApp.DoCallback(this))
{
//We cannot do a callback!
if (GetDownloadState() == DS_CONNECTING)
SetDownloadState(DS_LOWTOLOWIP);
else if (GetDownloadState() == DS_REQHASHSET)
{
SetDownloadState(DS_ONQUEUE);
reqfile->hashsetneeded = true;
}
if (GetUploadState() == US_CONNECTING)
{
if(Disconnected(_T("LowID->LowID and US_CONNECTING")))
{
delete this;
return false;
}
}
return true;
}
//We already know we are not firewalled here as the above condition already detected LowID->LowID and returned.
//If ANYTHING changes with the "if(!theApp.DoCallback(this))" above that will let you fall through
//with the condition that the source is firewalled and we are firewalled, we must
//recheck it before the this check..
if( HasValidBuddyID() && !GetBuddyIP() && !GetBuddyPort() && !theApp.serverconnect->IsLocalServer(GetServerIP(), GetServerPort()))
{
//This is a Kad firewalled source that we want to do a special callback because it has no buddyIP or buddyPort.
if( Kademlia::CKademlia::isConnected() )
{
//We are connect to Kad
ASSERT(Kademlia::CKademlia::getPrefs() != NULL);
if( Kademlia::CKademlia::getPrefs()->getTotalSource() > 0 || Kademlia::CSearchManager::alreadySearchingFor(Kademlia::CUInt128(GetBuddyID())))
{
//There are too many source lookups already or we are already searching this key.
SetDownloadState(DS_TOOMANYCONNSKAD);
return true;
}
}
}
}
if (!socket || !socket->IsConnected())
{
if (socket)
socket->Safe_Delete();
if (pClassSocket == NULL)
pClassSocket = RUNTIME_CLASS(CClientReqSocket);
socket = static_cast<CClientReqSocket*>(pClassSocket->CreateObject());
socket->SetClient(this);
if (!socket->Create())
{
socket->Safe_Delete();
return true;
}
}
else
{
ConnectionEstablished();
return true;
}
// MOD Note: Do not change this part - Merkur
if (HasLowID())
{
if (GetDownloadState() == DS_CONNECTING)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -