📄 listensocket.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.
// ListenSocket.cpp : implementation file
//
#include "stdafx.h"
#include "emule.h"
#include "ListenSocket.h"
#include "opcodes.h"
#include "KnownFile.h"
#include "sharedfilelist.h"
#include "uploadqueue.h"
#include "updownclient.h"
#include "clientlist.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// CClientReqSocket
CClientReqSocket::CClientReqSocket(CPreferences* in_prefs,CUpDownClient* in_client){
app_prefs = in_prefs;
client = in_client;
if (in_client)
client->socket = this;
theApp.listensocket->AddSocket(this);
ResetTimeOutTimer();
deletethis = false;
deltimer = 0;
}
CClientReqSocket::~CClientReqSocket(){
if (client)
client->socket = 0;
client = 0;
theApp.listensocket->RemoveSocket(this);
DEBUG_ONLY (theApp.clientlist->Debug_SocketDeleted(this));
}
void CClientReqSocket::ResetTimeOutTimer(){
timeout_timer = ::GetTickCount();
};
bool CClientReqSocket::CheckTimeOut(){
if (::GetTickCount() - timeout_timer > CONNECTION_TIMEOUT){
timeout_timer = ::GetTickCount();
Disconnect();
return true;
}
return false;
};
void CClientReqSocket::OnClose(int nErrorCode){
ASSERT (theApp.listensocket->IsValidSocket(this));
CEMSocket::OnClose(nErrorCode);
Disconnect();
};
void CClientReqSocket::Disconnect(){
AsyncSelect(0);
byConnected = ES_DISCONNECTED;
if (!client)
Safe_Delete();
else
client->Disconnected();
};
void CClientReqSocket::Delete_Timed(){
// it seems that MFC Sockets call socketfunctions after they are deleted, even if the socket is closed
// and select(0) is set. So we need to wait some time to make sure this doesn't happens
if (::GetTickCount() - deltimer > 10000)
delete this;
}
void CClientReqSocket::Safe_Delete(){
ASSERT (theApp.listensocket->IsValidSocket(this));
AsyncSelect(0);
deltimer = ::GetTickCount();
if (m_hSocket != INVALID_SOCKET)
ShutDown(2);
if (client)
client->socket = 0;
client = 0;
byConnected = ES_DISCONNECTED;
deletethis = true;
}
bool CClientReqSocket::ProcessPacket(char* packet, uint32 size, uint8 opcode){
try{
try{
if (!client && opcode != OP_HELLO)
throw GetResString(IDS_ERR_NOHELLO);
switch(opcode){
case OP_HELLOANSWER:{
theApp.downloadqueue->AddDownDataOverheadOther(size);
client->ProcessHelloAnswer(packet,size);
if (client){
client->ConnectionEstablished();
theApp.emuledlg->transferwnd.clientlistctrl.RefreshClient(client);
}
break;
}
case OP_HELLO:{
theApp.downloadqueue->AddDownDataOverheadOther(size);
if (!client){
// create new client to save standart informations
client = new CUpDownClient(this);
}
client->ProcessHelloPacket(packet,size);
// now we check if we now this client already. if yes this socket will
// be attached to the known client, the new client will be deleted
// and the var. "client" will point to the known client.
// if not we keep our new-constructed client ;)
if (theApp.clientlist->AttachToAlreadyKnown(&client,this)){
// update the old client informations
client->ProcessHelloPacket(packet,size);
}
else {
theApp.clientlist->AddClient(client);
client->SetCommentDirty();
}
theApp.emuledlg->transferwnd.clientlistctrl.RefreshClient(client);
// if IP is filtered, dont reply but disconnect...
if (theApp.ipfilter->IsFiltered(client->GetIP())) {
theApp.emuledlg->AddDebugLogLine(true,GetResString(IDS_IPFILTERED),client->GetFullIP(),theApp.ipfilter->GetLastHit());
client->Disconnected();
theApp.stat_filteredclients++;
break;
}
// send a response packet with standart informations
if (client->GetClientSoft() == SO_EMULE )
client->SendMuleInfoPacket(false);
client->SendHelloAnswer();
if (client)
client->ConnectionEstablished();
break;
}
case OP_FILEREQUEST:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
if (size == 16 || (size > 16 && client->GetExtendedRequestsVersion() > 0)){
if (!client->GetWaitStartTime())
client->SetWaitStartTime();
uchar reqfileid[16];
memcpy(reqfileid,packet,16);
CKnownFile* reqfile = theApp.sharedfiles->GetFileByID(reqfileid);
if (!reqfile){
// DbT:FileRequest
// send file request no such file packet (0x48)
Packet* replypacket = new Packet(OP_FILEREQANSNOFIL, 16);
memcpy(replypacket->pBuffer, packet, 16);
theApp.uploadqueue->AddUpDataOverheadFileRequest(replypacket->size);
SendPacket(replypacket, true);
// DbT:End
break;
}
// if wer are downloading this file, this could be a new source
if (reqfile->IsPartFile())
if( theApp.glob_prefs->GetMaxSourcePerFile() > ((CPartFile*)reqfile)->GetSourceCount() ) //<<--
theApp.downloadqueue->CheckAndAddKnownSource((CPartFile*)reqfile,client);
// check to see if this is a new file they are asking for
if(memcmp(client->GetUploadFileID(), packet, 16) != 0)
client->SetCommentDirty();
// CKnownFile* clientreqfile = theApp.sharedfiles->GetFileByID(client->GetUploadFileID());
// if( clientreqfile )
// clientreqfile->SubQueuedCount();
// reqfile->AddQueuedCount();
// send filename etc
client->SetUploadFileID((uchar*)packet);
// memcpy(client->reqfileid,packet,16);
CMemFile* data = new CMemFile();
data->Write(reqfile->GetFileHash(),16);
uint16 namelength = (uint16)strlen(reqfile->GetFileName());
data->Write(&namelength,2);
data->Write(reqfile->GetFileName(),namelength);
client->ProcessUpFileStatus(packet,size);
Packet* packet = new Packet(data);
packet->opcode = OP_FILEREQANSWER;
delete data;
theApp.uploadqueue->AddUpDataOverheadFileRequest(packet->size);
SendPacket(packet,true);
/* done with "OP_SETREQFILEID" now
//send filestatus
data = new CMemFile();
data->Write(reqfile->GetFileHash(),16);
if (reqfile->IsPartFile())
((CPartFile*)reqfile)->WritePartStatus(data);
else{
uint32 null = 0;
data->Write(&null,3);
}
packet = new Packet(data);
packet->opcode = OP_FILESTATUS;
delete data;
theApp.uploadqueue->AddUpDataOverheadFileRequest(packet->size);
SendPacket(packet,true);
*/
client->SendCommentInfo(reqfile);
break;
}
throw GetResString(IDS_ERR_WRONGPACKAGESIZE);
break;
}
case OP_FILEREQANSNOFIL:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
// DbT:FileRequest
if (size == 16) {
// if that client do not have my file maybe has another different
CPartFile* reqfile = theApp.downloadqueue->GetFileByID((uchar*)packet);
if (!reqfile)
break;
// we try to swap to another file ignoring no needed parts files
if (client) switch (client->GetDownloadState()) {
case DS_ONQUEUE:
case DS_NONEEDEDPARTS:
if (!client->SwapToAnotherFile(false)) {
theApp.downloadqueue->RemoveSource(client, true);
}
break;
}
break;
}
throw GetResString(IDS_ERR_WRONGPACKAGESIZE);
break;
// DbT:End
}
case OP_FILEREQANSWER:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
client->ProcessFileInfo(packet,size);
break;
}
case OP_FILESTATUS:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
client->ProcessFileStatus(packet,size);
break;
}
case OP_STARTUPLOADREQ:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
if( size == 16 ){
uchar reqfileid[16];
memcpy(reqfileid,packet,16);
CKnownFile* reqfile = theApp.sharedfiles->GetFileByID(reqfileid);
if (reqfile){
if (reqfile->IsPartFile())
if( theApp.glob_prefs->GetMaxSourcePerFile() > ((CPartFile*)reqfile)->GetSourceCount() ) //<<--
theApp.downloadqueue->CheckAndAddKnownSource((CPartFile*)reqfile,client);
if(memcmp(client->GetUploadFileID(), packet, 16) != 0)
client->SetCommentDirty();
client->SetUploadFileID((uchar*)packet);
client->SendCommentInfo(reqfile);
}
}
theApp.uploadqueue->AddClientToQueue(client);
break;
}
case OP_QUEUERANK:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
CSafeMemFile* data = new CSafeMemFile((BYTE*)packet,size);
uint32 rank;
data->Read(&rank,4);
client->SetRemoteQueueRank(rank);
delete data;
break;
}
case OP_ACCEPTUPLOADREQ:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
if (client->GetDownloadState() == DS_ONQUEUE ){
client->SetDownloadState(DS_DOWNLOADING);
client->SendBlockRequests();
}
break;
}
case OP_REQUESTPARTS:{
theApp.downloadqueue->AddDownDataOverheadFileRequest(size);
CSafeMemFile* data = new CSafeMemFile((BYTE*)packet,size);
uchar reqfilehash[16];
data->Read(reqfilehash,16);
Requested_Block_Struct* reqblock1 = new Requested_Block_Struct;
Requested_Block_Struct* reqblock2 = new Requested_Block_Struct;
Requested_Block_Struct* reqblock3 = new Requested_Block_Struct;
data->Read(&reqblock1->StartOffset,4);
data->Read(&reqblock2->StartOffset,4);
data->Read(&reqblock3->StartOffset,4);
data->Read(&reqblock1->EndOffset,4);
data->Read(&reqblock2->EndOffset,4);
data->Read(&reqblock3->EndOffset,4);
memcpy(&reqblock1->FileID,reqfilehash,16);
memcpy(&reqblock2->FileID,reqfilehash,16);
memcpy(&reqblock3->FileID,reqfilehash,16);
if (reqblock1->EndOffset-reqblock1->StartOffset == 0)
delete reqblock1;
else
client->AddReqBlock(reqblock1);
if (reqblock2->EndOffset-reqblock2->StartOffset == 0)
delete reqblock2;
else
client->AddReqBlock(reqblock2);
if (reqblock3->EndOffset-reqblock3->StartOffset == 0)
delete reqblock3;
else
client->AddReqBlock(reqblock3);
delete data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -