📄 baseclient.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.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 "updownclient.h"
#include "emule.h"
#include "uploadqueue.h"
#include "Clientlist.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// members of CUpDownClient
// which are used by down and uploading functions
CUpDownClient::CUpDownClient(CClientReqSocket* sender){
socket = sender;
reqfile = 0;
Init();
}
CUpDownClient::CUpDownClient(uint16 in_port, uint32 in_userid,uint32 in_serverip, uint16 in_serverport,CPartFile* in_reqfile){
socket = 0;
Init();
m_nUserID = in_userid;
m_nUserPort = in_port;
sourcesslot=m_nUserID%SOURCESSLOTS;
if (!HasLowID())
sprintf(m_szFullUserIP,"%i.%i.%i.%i",(uint8)m_nUserID,(uint8)(m_nUserID>>8),(uint8)(m_nUserID>>16),(uint8)(m_nUserID>>24));
m_dwServerIP = in_serverip;
m_nServerPort = in_serverport;
reqfile = in_reqfile;
ReGetClientSoft();
}
void CUpDownClient::Init(){
memset(m_szFullUserIP,0,21);
credits = 0;
AddNextConnect = false; // VQB Fix for LowID slots only on connection
m_nAvDownDatarate = 0;
m_nAvUpDatarate = 0;
m_byChatstate = 0;
m_cShowDR = 0;
m_nUDPPort = 0;
m_cFailed = 0;
m_dwBanTime = 0;
m_nMaxSendAllowed = 0;
m_nTransferedUp = 0;
m_cSendblock = 0;
m_cAsked = 0;
m_cDownAsked = 0;
dataratems = 0;
m_nUpDatarate = 0;
m_pszUsername = 0;
m_dwUserIP = 0;
m_nUserID = 0;
m_nServerPort = 0;
m_bBanned = false;
m_iFileListRequested = 0;
m_dwLastUpRequest = 0;
m_bEmuleProtocol = false;
usedcompressiondown = false;
m_bUsedComprUp = 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_dwLastAskedTime = 0;
m_nDownloadState = DS_NONE;
m_pszClientFilename = 0;
m_dwUploadTime = 0;
m_nTransferedDown = 0;
m_nDownDatarate = 0;
m_nDownDataRateMS = 0;
m_byUploadState = US_NONE;
m_dwLastBlockReceived = 0;
m_byEmuleVersion = 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_byCompatibleClient = 0;
m_bIsHybrid = false;
m_Friend = NULL;
m_iRate=0;
m_bMsgFiltered=false;
m_strComment="";
m_nCurSessionUp = 0;
m_nSumForAvgDownDataRate = 0;
m_nSumForAvgUpDataRate = 0;
m_clientSoft=SO_UNKNOWN;
m_bRemoteQueueFull = false;
memset( m_achUserHash, 0, 16);
SetWaitStartTime();
if (socket){
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
uint32 nSockAddrLen = sizeof(sockAddr);
socket->GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
m_dwUserIP = sockAddr.sin_addr.S_un.S_addr;
strcpy(m_szFullUserIP,inet_ntoa(sockAddr.sin_addr));
}
sourcesslot=0;
}
CUpDownClient::~CUpDownClient(){
//Beep(400,5);
theApp.clientlist->RemoveClient(this);
if (m_Friend){
m_Friend->m_LinkedClient = NULL;
theApp.friendlist->RefreshFriend(m_Friend);
m_Friend = NULL;
}
if (m_pszClientFilename)
delete[] m_pszClientFilename;
if (socket){
socket->client = 0;
socket->Safe_Delete();
}
if (m_pszUsername)
delete[] m_pszUsername;
if (m_abyPartStatus)
delete[] m_abyPartStatus;
if (m_abyUpPartStatus)
delete[] m_abyUpPartStatus;
ClearUploadBlockRequests();
for (POSITION pos = m_DownloadBlocks_list.GetHeadPosition();pos != 0;m_DownloadBlocks_list.GetNext(pos))
delete m_DownloadBlocks_list.GetAt(pos);
m_DownloadBlocks_list.RemoveAll();
for (POSITION pos = m_RequestedFiles_list.GetHeadPosition();pos != 0;m_RequestedFiles_list.GetNext(pos))
delete m_RequestedFiles_list.GetAt(pos);
m_RequestedFiles_list.RemoveAll();
for (POSITION pos = m_PendingBlocks_list.GetHeadPosition();pos != 0;m_PendingBlocks_list.GetNext(pos)){
Pending_Block_Struct *pending = m_PendingBlocks_list.GetAt(pos);
delete pending->block;
// Not always allocated
if (pending->zStream) delete pending->zStream;
delete pending;
}
if (m_iRate>0 || m_strComment.GetLength()>0) {
m_iRate=0; m_strComment="";
reqfile->UpdateFileRatingCommentAvail();
}
m_PendingBlocks_list.RemoveAll();
m_AvarageUDR_list.RemoveAll();
m_AvarageDDR_list.RemoveAll();
DEBUG_ONLY (theApp.listensocket->Debug_ClientDeleted(this));
this->SetUploadFileID(NULL);
}
void CUpDownClient::ProcessHelloPacket(char* pachPacket, uint32 nSize){
CSafeMemFile* data = new CSafeMemFile((BYTE*)pachPacket,nSize);
uint8 hashsize;
data->Read(&hashsize,1);
this->ProcessHelloTypePacket(data);
delete data;
}
void CUpDownClient::ProcessHelloAnswer(char* pachPacket, uint32 nSize){
CSafeMemFile* data = new CSafeMemFile((BYTE*)pachPacket,nSize);
this->ProcessHelloTypePacket(data);
delete data;
}
void CUpDownClient::ProcessHelloTypePacket(CSafeMemFile* data){
m_bIsHybrid = false;
data->Read(&m_achUserHash,16);
uint32 nUserID;
data->Read(&nUserID,4);
if (!m_nUserID)
m_nUserID = nUserID;
data->Read(&m_nUserPort,2); // hmm clientport is sent twice - why?
uint32 tagcount;
data->Read(&tagcount,4);
for (int i = 0;i != tagcount; i++){
CTag* temptag = new CTag(data);
switch(temptag->tag->specialtag){
case CT_NAME:
if (m_pszUsername)
delete[] m_pszUsername;
if( temptag->tag->stringvalue )
m_pszUsername = nstrdup(temptag->tag->stringvalue);
else
m_pszUsername=NULL;
break;
case CT_VERSION:
m_nClientVersion = temptag->tag->intvalue;
break;
case CT_PORT:
m_nUserPort = temptag->tag->intvalue;
break;
}
delete temptag;
}
data->Read(&m_dwServerIP,4);
data->Read(&m_nServerPort,2);
// 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() == 4 ){
// uint32 test;
// data->Read(&test,4);
m_bIsHybrid = true;
}
if( m_nClientVersion > 10000 && m_nClientVersion < 100000 )
m_nClientVersion = m_nClientVersion - (m_nClientVersion/10000)*10000;
if( m_nClientVersion > 1000 )
m_nClientVersion = m_nClientVersion - (m_nClientVersion/1000)*1000;
if( m_nClientVersion < 100 )
m_nClientVersion *= 10;
// tecxx 1609 2002 - add client's servet to serverlist (Moved to uploadqueue.cpp)
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
uint32 nSockAddrLen = sizeof(sockAddr);
socket->GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
m_dwUserIP = sockAddr.sin_addr.S_un.S_addr;
strcpy(m_szFullUserIP,inet_ntoa(sockAddr.sin_addr));
// get client credits
// key, 255.255.0.0 subnetmask
if (theApp.glob_prefs->AddServersFromClient()){
in_addr addhost;
addhost.S_un.S_addr = m_dwServerIP;
CServer* addsrv = new CServer(m_nServerPort, inet_ntoa(addhost));
addsrv->SetListName(addsrv->GetAddress());
if (!theApp.emuledlg->serverwnd.serverlistctrl.AddServer(addsrv, true))
delete addsrv;
/*else
theApp.emuledlg->AddLogLine(false,"Added new server: %s:%d", srv->GetFullIP(), srv->GetPort());*/
}
if(!HasLowID() && m_nUserID != m_dwUserIP)
m_nUserID = m_dwUserIP;
uchar key[16];
memcpy(key,m_achUserHash,16);
credits = theApp.clientcredits->GetCredit(key);
if ( (m_Friend = theApp.friendlist->LinkFriend(key, m_dwUserIP, m_nUserPort) ) != NULL){
m_Friend->m_LinkedClient = this;
m_Friend->m_dwHasHash = 1;
for( int i = 0; i < 16; i++ )
m_Friend->m_abyUserhash[i] = GetUserHash()[i];
m_Friend->m_strName.Format("%s", m_pszUsername);
m_Friend->m_dwLastUsedIP = m_dwUserIP;
m_Friend->m_nLastUsedPort = m_nUserPort;
theApp.friendlist->RefreshFriend(m_Friend);
}
ReGetClientSoft();
}
void CUpDownClient::SendHelloPacket(){
// if IP is filtered, dont greet him but disconnect...
if (socket){
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
uint32 nSockAddrLen = sizeof(sockAddr);
socket->GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
if ( theApp.ipfilter->IsFiltered(sockAddr.sin_addr.S_un.S_addr)) {
theApp.emuledlg->AddDebugLogLine(true,GetResString(IDS_IPFILTERED),GetFullIP(),theApp.ipfilter->GetLastHit());
Disconnected();
theApp.stat_filteredclients++;
return;
}
}
CMemFile* data = new CMemFile();
uint8 hashsize = 16;
data->Write(&hashsize,1);
SendHelloTypePacket(data);
Packet* packet = new Packet(data);
delete data;
packet->opcode = OP_HELLO;
if (socket){
theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
socket->SendPacket(packet,true);
}
}
void CUpDownClient::SendMuleInfoPacket(bool bAnswer){
CMemFile* data = new CMemFile();
uint8 version = CURRENT_VERSION_SHORT;
data->Write(&version,1);
uint8 protversion = EMULE_PROTOCOL;
data->Write(&protversion,1);
uint32 tagcount = 6;
data->Write(&tagcount,4);
CTag tag(ET_COMPRESSION,1);
tag.WriteTagToFile(data);
CTag tag2(ET_UDPVER,2);
tag2.WriteTagToFile(data);
CTag tag3(ET_UDPPORT,theApp.glob_prefs->GetUDPPort());
tag3.WriteTagToFile(data);
CTag tag4(ET_SOURCEEXCHANGE,2);
tag4.WriteTagToFile(data);
CTag tag5(ET_COMMENTS,1);
tag5.WriteTagToFile(data);
CTag tag6(ET_EXTENDEDREQUEST,1);
tag6.WriteTagToFile(data);
Packet* packet = new Packet(data,OP_EMULEPROT);
delete data;
if (!bAnswer)
packet->opcode = OP_EMULEINFO;
else
packet->opcode = OP_EMULEINFOANSWER;
if (socket){
theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
socket->SendPacket(packet,true,true);
}
}
void CUpDownClient::ProcessMuleInfoPacket(char* pachPacket, uint32 nSize){
CSafeMemFile* data = new CSafeMemFile((BYTE*)pachPacket,nSize);
m_byCompatibleClient = 0;
//The version number part of this packet will soon be useless since it is only able to go to v.99.
//Why the version is a uint8 and why it was not done as a tag like the eDonkey hello packet is not known..
//Therefore, sooner or later, we are going to have to switch over to using the eDonkey hello packet to set the version.
//No sense making a third value sent for versions..
data->Read(&m_byEmuleVersion,1);
if( m_byEmuleVersion == 0x2B )
m_byEmuleVersion = 0x22;
uint8 protversion;
data->Read(&protversion,1);
//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;
} else {
delete data;
return;
}
m_bEmuleProtocol = true;
uint32 tagcount;
data->Read(&tagcount,4);
for (int i = 0;i != tagcount; i++){
CTag* temptag = new CTag(data);
switch(temptag->tag->specialtag){
case ET_COMPRESSION:
m_byDataCompVer = temptag->tag->intvalue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -