📄 baseclient.cpp
字号:
case CT_EMULE_VERSION:
// 8 Compatible Client ID
// 7 Mjr Version (Doesn't really matter..)
// 7 Min Version (Only need 0-99)
// 3 Upd Version (Only need 0-5)
// 7 Bld Version (Only need 0-99) -- currently not used
m_byCompatibleClient = (temptag.tag.intvalue >> 24);
m_nClientVersion = temptag.tag.intvalue & 0x00ffffff;
m_byEmuleVersion = 0x99;
m_fSharedDirectories = 1;
dwEmuleTags |= 4;
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" Comptbl=%u ClientVer=%u.%u.%u.%u"), m_byCompatibleClient, (m_nClientVersion >> 17) & 0x7f, (m_nClientVersion >> 10) & 0x7f, (m_nClientVersion >> 7) & 0x07, m_nClientVersion & 0x7f);
break;
default:
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" ***UnkTag: %s"), temptag.GetFullInfo());
}
}
m_nUserPort = nUserPort;
m_dwServerIP = data->ReadUInt32();
m_nServerPort = data->ReadUInt16();
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" Server=%s:%u"), ipstr(m_dwServerIP), m_nServerPort);
// Hybrid now has an extra uint32.. What is it for?
// Also, many clients seem to send an extra 6? These are not eDonkeys or Hybrids..
if ( data->GetLength() - data->GetPosition() == sizeof(uint32) ){
uint32 test = data->ReadUInt32();
if (test == 'KDLM')
{
m_bIsML = true;
if (bDbgInfo)
m_strHelloInfo += _T(" ***AddData: \"MLDK\"");
}
else{
m_bIsHybrid = true;
m_fSharedDirectories = 1;
if (bDbgInfo)
m_strHelloInfo.AppendFormat(_T(" ***AddData: uint32=%u (0x%08x)"), test, test);
}
}
else if (bDbgInfo && data->GetPosition() < data->GetLength()){
UINT uAddHelloDataSize = (UINT)(data->GetLength() - data->GetPosition());
if (uAddHelloDataSize == sizeof(uint32)){
DWORD dwAddHelloInt32 = data->ReadUInt32();
m_strHelloInfo.AppendFormat(_T(" ***AddData: uint32=%u (0x%08x)"), dwAddHelloInt32, dwAddHelloInt32);
}
else if (uAddHelloDataSize == sizeof(uint32)+sizeof(uint16)){
DWORD dwAddHelloInt32 = data->ReadUInt32();
WORD w = data->ReadUInt16();
m_strHelloInfo.AppendFormat(_T(" ***AddData: uint32=%u (0x%08x), uint16=%u (0x%04x)"), dwAddHelloInt32, dwAddHelloInt32, w, w);
}
else
m_strHelloInfo.AppendFormat(_T(" ***AddData: %u bytes"), uAddHelloDataSize);
}
SOCKADDR_IN sockAddr = {0};
int nSockAddrLen = sizeof(sockAddr);
socket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
m_dwUserIP = sockAddr.sin_addr.S_un.S_addr;
m_nConnectIP = m_dwUserIP;
if (thePrefs.AddServersFromClient() && m_dwServerIP && m_nServerPort){
CServer* addsrv = new CServer(m_nServerPort, ipstr(m_dwServerIP));
addsrv->SetListName(addsrv->GetAddress());
if (!theApp.emuledlg->serverwnd->serverlistctrl.AddServer(addsrv, true))
delete addsrv;
}
//(a)If this is a highID user, store the ID in the Hybrid format.
//(b)Some older clients will not send a ID, these client are HighID users that are not connected to a server.
//(c)Kad users with a *.*.*.0 IPs will look like a lowID user they are actually a highID user.. They can be detected easily
//because they will send a ID that is the same as their IP..
if(!HasLowID() || m_nUserIDHybrid == 0 || m_nUserIDHybrid == m_dwUserIP )
m_nUserIDHybrid = ntohl(m_dwUserIP);
CClientCredits* pFoundCredits = theApp.clientcredits->GetCredit(m_achUserHash);
if (credits == NULL){
credits = pFoundCredits;
if (!theApp.clientlist->ComparePriorUserhash(m_dwUserIP, m_nUserPort, pFoundCredits)){
if (thePrefs.GetLogBannedClients())
AddDebugLogLine(false, _T("Clients: %s (%s), Banreason: Userhash changed (Found in TrackedClientsList)"), GetUserName(), ipstr(GetConnectIP()));
Ban();
}
}
else if (credits != pFoundCredits){
// userhash change ok, however two hours "waittime" before it can be used
credits = pFoundCredits;
if (thePrefs.GetLogBannedClients())
AddDebugLogLine(false, _T("Clients: %s (%s), Banreason: Userhash changed"), GetUserName(), ipstr(GetConnectIP()));
Ban();
}
if ((m_Friend = theApp.friendlist->SearchFriend(m_achUserHash, m_dwUserIP, m_nUserPort)) != NULL){
// Link the friend to that client
m_Friend->SetLinkedClient(this);
}
else{
// avoid that an unwanted client instance keeps a friend slot
SetFriendSlot(false);
}
// check for known major gpl breaker
CString strBuffer = m_pszUsername;
strBuffer.MakeUpper();
strBuffer.Remove(_T(' '));
if (strBuffer.Find(_T("EMULE-CLIENT")) != -1 || strBuffer.Find(_T("POWERMULE")) != -1 ){
m_bGPLEvildoer = true;
}
ReGetClientSoft();
m_byInfopacketsReceived |= IP_EDONKEYPROTPACK;
// check if at least CT_EMULEVERSION was received, all other tags are optional
bool bIsMule = (dwEmuleTags & 0x04) == 0x04;
if (bIsMule){
m_bEmuleProtocol = true;
m_byInfopacketsReceived |= IP_EMULEPROTPACK;
}
if (thePrefs.GetVerbose() && GetServerIP() == INADDR_NONE)
AddDebugLogLine(false, _T("Received invalid server IP %s from %s"), ipstr(GetServerIP()), DbgGetClientInfo());
if( GetKadPort() && Kademlia::CKademlia::isRunning() )
{
Kademlia::CKademlia::getUDPListener()->bootstrap(ntohl(GetIP()), GetKadPort());
}
return bIsMule;
}
// returns 'false', if client instance was deleted!
bool CUpDownClient::SendHelloPacket(){
if (socket == NULL){
ASSERT(0);
return true;
}
CSafeMemFile data(128);
data.WriteUInt8(16); // size of userhash
SendHelloTypePacket(&data);
Packet* packet = new Packet(&data);
packet->opcode = OP_HELLO;
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__Hello", this);
theStats.AddUpDataOverheadOther(packet->size);
socket->SendPacket(packet,true);
m_bHelloAnswerPending = true;
return true;
}
void CUpDownClient::SendMuleInfoPacket(bool bAnswer){
if (socket == NULL){
ASSERT(0);
return;
}
CSafeMemFile data(128);
data.WriteUInt8(theApp.m_uCurVersionShort);
data.WriteUInt8(EMULE_PROTOCOL);
data.WriteUInt32(7); // nr. of tags
CTag tag(ET_COMPRESSION,1);
tag.WriteTagToFile(&data);
CTag tag2(ET_UDPVER,4);
tag2.WriteTagToFile(&data);
CTag tag3(ET_UDPPORT,thePrefs.GetUDPPort());
tag3.WriteTagToFile(&data);
CTag tag4(ET_SOURCEEXCHANGE,3);
tag4.WriteTagToFile(&data);
CTag tag5(ET_COMMENTS,1);
tag5.WriteTagToFile(&data);
CTag tag6(ET_EXTENDEDREQUEST,2);
tag6.WriteTagToFile(&data);
uint32 dwTagValue = (theApp.clientcredits->CryptoAvailable() ? 3 : 0);
if (thePrefs.CanSeeShares() != vsfaNobody) // set 'Preview supported' only if 'View Shared Files' allowed
dwTagValue |= 128;
CTag tag7(ET_FEATURES, dwTagValue);
tag7.WriteTagToFile(&data);
Packet* packet = new Packet(&data,OP_EMULEPROT);
if (!bAnswer)
packet->opcode = OP_EMULEINFO;
else
packet->opcode = OP_EMULEINFOANSWER;
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend(!bAnswer ? "OP__EmuleInfo" : "OP__EmuleInfoAnswer", this);
theStats.AddUpDataOverheadOther(packet->size);
socket->SendPacket(packet,true,true);
}
void CUpDownClient::ProcessMuleInfoPacket(char* pachPacket, uint32 nSize)
{
bool bDbgInfo = thePrefs.GetUseDebugDevice();
m_strMuleInfo.Empty();
CSafeMemFile data((BYTE*)pachPacket,nSize);
m_byCompatibleClient = 0;
m_byEmuleVersion = data.ReadUInt8();
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T("EmuleVer=0x%x"), (UINT)m_byEmuleVersion);
if( m_byEmuleVersion == 0x2B )
m_byEmuleVersion = 0x22;
uint8 protversion = data.ReadUInt8();
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" ProtVer=%u"), (UINT)protversion);
//implicitly supported options by older clients
if (protversion == EMULE_PROTOCOL) {
//in the future do not use version to guess about new features
if(m_byEmuleVersion < 0x25 && m_byEmuleVersion > 0x22)
m_byUDPVer = 1;
if(m_byEmuleVersion < 0x25 && m_byEmuleVersion > 0x21)
m_bySourceExchangeVer = 1;
if(m_byEmuleVersion == 0x24)
m_byAcceptCommentVer = 1;
// Shared directories are requested from eMule 0.28+ because eMule 0.27 has a bug in
// the OP_ASKSHAREDFILESDIR handler, which does not return the shared files for a
// directory which has a trailing backslash.
if(m_byEmuleVersion >= 0x28 && !m_bIsML) // MLdonkey currently does not support shared directories
m_fSharedDirectories = 1;
} else {
return;
}
m_bEmuleProtocol = true;
uint32 tagcount = data.ReadUInt32();
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" Tags=%u"), (UINT)tagcount);
for (uint32 i = 0;i < tagcount; i++){
CTag temptag(&data);
switch(temptag.tag.specialtag){
case ET_COMPRESSION:
// Bits 31- 8: 0 - reserved
// Bits 7- 0: data compression version
m_byDataCompVer = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" Compr=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_UDPPORT:
// Bits 31-16: 0 - reserved
// Bits 15- 0: UDP port
m_nUDPPort = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" UDPPort=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_UDPVER:
// Bits 31- 8: 0 - reserved
// Bits 7- 0: UDP protocol version
m_byUDPVer = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" UDPVer=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_SOURCEEXCHANGE:
// Bits 31- 8: 0 - reserved
// Bits 7- 0: source exchange protocol version
m_bySourceExchangeVer = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" SrcExch=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_COMMENTS:
// Bits 31- 8: 0 - reserved
// Bits 7- 0: comments version
m_byAcceptCommentVer = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" Commnts=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_EXTENDEDREQUEST:
// Bits 31- 8: 0 - reserved
// Bits 7- 0: extended requests version
m_byExtendedRequestsVer = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" ExtReq=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_COMPATIBLECLIENT:
// Bits 31- 8: 0 - reserved
// Bits 7- 0: compatible client ID
m_byCompatibleClient = temptag.tag.intvalue;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" Comptbl=%u"), (UINT)temptag.tag.intvalue);
break;
case ET_FEATURES:
// Bits 31- 8: 0 - reserved
// Bit 7: Preview
// Bit 6- 0: secure identification
m_bySupportSecIdent = (temptag.tag.intvalue ) & 3;
m_fSupportsPreview = (temptag.tag.intvalue >> 7) & 1;
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" SecIdent=%u Preview=%u"), m_bySupportSecIdent, m_fSupportsPreview);
break;
case ET_MOD_VERSION:
if (temptag.tag.type == 2)
m_strModVersion = temptag.tag.stringvalue;
else if (temptag.tag.type == 3)
m_strModVersion.Format(_T("ModID=%u"), temptag.tag.intvalue);
else
m_strModVersion = _T("ModID=<Unknwon>");
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" Mod=%s"), m_strModVersion);
CheckForGPLEvilDoer();
break;
default:
if (bDbgInfo)
m_strMuleInfo.AppendFormat(_T(" ***EmuleUnkTag: 0x%02x=%u"), temptag.tag.specialtag, (UINT)temptag.tag.intvalue);
}
}
if( m_byDataCompVer == 0 ){
m_bySourceExchangeVer = 0;
m_byExtendedRequestsVer = 0;
m_byAcceptCommentVer = 0;
m_nUDPPort = 0;
}
if (bDbgInfo && data.GetPosition() < data.GetLength()){
m_strMuleInfo.AppendFormat(_T(" ***AddData: %u bytes"), data.GetLength() - data.GetPosition());
}
ReGetClientSoft();
m_byInfopacketsReceived |= IP_EMULEPROTPACK;
if (thePrefs.GetVerbose() && GetServerIP() == INADDR_NONE)
AddDebugLogLine(false, _T("Received invalid server IP %s from %s"), ipstr(GetServerIP()), DbgGetClientInfo());
}
void CUpDownClient::SendHelloAnswer(){
if (socket == NULL){
ASSERT(0);
return;
}
CSafeMemFile data(128);
SendHelloTypePacket(&data);
Packet* packet = new Packet(&data);
packet->opcode = OP_HELLOANSWER;
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__HelloAnswer", this);
theStats.AddUpDataOverheadOther(packet->size);
socket->SendPacket(packet,true);
}
void CUpDownClient::SendHelloTypePacket(CSafeMemFile* data)
{
data->WriteHash16(thePrefs.GetUserHash());
uint32 clientid;
clientid = theApp.GetID();
data->WriteUInt32(clientid);
data->WriteUInt16(thePrefs.GetPort());
uint32 tagcount = 5;
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():"Please use a GPL-conform version of eMule" );
tagName.WriteTagToFile(data);
// 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,
(kadUDPPort << 16) |
((uint32)thePrefs.GetUDPPort() ) );
tagUdpPorts.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;
CTag tagMisOptions(CT_EMULE_MISCOPTIONS1,
// ( << 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -