📄 listensocket.cpp
字号:
theStats.AddDownDataOverheadFileRequest(uRawSize);
if (!client->ProcessPeerCacheQuery(packet, size))
{
CSafeMemFile dataSend(128);
dataSend.WriteUInt8(PCPCK_VERSION);
dataSend.WriteUInt8(PCOP_NONE);
if (thePrefs.GetDebugClientTCPLevel() > 0){
DebugSend("OP__PeerCacheAnswer", client);
Debug(_T(" %s\n"), _T("Not supported"));
}
Packet* pEd2kPacket = new Packet(&dataSend, OP_EMULEPROT, OP_PEERCACHE_ANSWER);
theStats.AddUpDataOverheadFileRequest(pEd2kPacket->size);
SendPacket(pEd2kPacket);
}
break;
}
case OP_PEERCACHE_ANSWER:
{
theStats.AddDownDataOverheadFileRequest(uRawSize);
if ( (!client->ProcessPeerCacheAnswer(packet, size)) && client->GetDownloadState() != DS_NONEEDEDPARTS)
{
// We have sent a PeerCache Query to the remote client, for any reason the remote client
// can not process it -> fall back to ed2k download.
client->SetPeerCacheDownState(PCDS_NONE);
ASSERT( client->m_pPCDownSocket == NULL );
// PC-TODO: Check client state.
ASSERT( client->GetDownloadState() == DS_DOWNLOADING );
client->SetDownloadState(DS_ONQUEUE); // clear block requests
client->StartDownload();
}
break;
}
case OP_PEERCACHE_ACK:
{
theStats.AddDownDataOverheadFileRequest(uRawSize);
client->ProcessPeerCacheAcknowledge(packet, size);
break;
}
case OP_PUBLICIP_ANSWER:
{
theStats.AddDownDataOverheadOther(uRawSize);
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugRecv("OP_PublicIPAns", client);
client->ProcessPublicIPAnswer((BYTE*)packet,size);
break;
}
case OP_PUBLICIP_REQ:
{
theStats.AddDownDataOverheadOther(uRawSize);
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugRecv("OP_PublicIPReq", client);
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__PublicIPAns", client);
Packet* pPacket = new Packet(OP_PUBLICIP_ANSWER, 4, OP_EMULEPROT);
PokeUInt32(pPacket->pBuffer, client->GetIP());
theStats.AddUpDataOverheadOther(pPacket->size);
SendPacket(pPacket);
break;
}
default:
theStats.AddDownDataOverheadOther(uRawSize);
PacketToDebugLogLine(_T("eMule"), packet, size, opcode, DLP_DEFAULT);
break;
}
}
catch(CFileException* error)
{
error->Delete();
throw GetResString(IDS_ERR_INVALIDPACKAGE);
}
catch(CMemoryException* error)
{
error->Delete();
throw CString(_T("Memory exception"));
}
}
catch(CClientException* ex) // nearly same as the 'CString' exception but with optional deleting of the client
{
if (thePrefs.GetVerbose() && !ex->m_strMsg.IsEmpty())
AddDebugLogLine(false, _T("%s - while processing eMule packet: opcode=%s size=%u; %s"), ex->m_strMsg, DbgGetMuleClientTCPOpcode(opcode), size, DbgGetClientInfo());
if (client && ex->m_bDelete)
client->SetDownloadState(DS_ERROR);
Disconnect(ex->m_strMsg);
ex->Delete();
return false;
}
catch(CString error)
{
if (thePrefs.GetVerbose() && !error.IsEmpty())
AddDebugLogLine(false, _T("%s - while processing eMule packet: opcode=%s size=%u; %s"), error, DbgGetMuleClientTCPOpcode(opcode), size, DbgGetClientInfo());
if (client)
client->SetDownloadState(DS_ERROR);
Disconnect(_T("ProcessExtPacket error. ") + error);
return false;
}
return true;
}
void CClientReqSocket::PacketToDebugLogLine(LPCTSTR protocol, const char* packet, uint32 size, UINT opcode, EDebugLogPriority dlpPriority)
{
if (thePrefs.GetVerbose())
{
CString buffer;
buffer.Format(_T("unknown %s protocol opcode: 0x%02x, size=%u, data=["), protocol, opcode, size);
for (uint32 i = 0; i < size && i < 50; i++){
if (i > 0)
buffer += _T(' ');
TCHAR temp[3];
_stprintf(temp, _T("%02x"), (uint8)packet[i]);
buffer += temp;
}
buffer += (i == size) ? _T("]") : _T("..]");
DbgAppendClientInfo(buffer);
AddDebugLogLine(dlpPriority, false, _T("%s"), buffer);
}
}
CString CClientReqSocket::DbgGetClientInfo()
{
CString str;
SOCKADDR_IN sockAddr = {0};
int nSockAddrLen = sizeof(sockAddr);
GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
if (sockAddr.sin_addr.S_un.S_addr != 0 && (client == NULL || sockAddr.sin_addr.S_un.S_addr != client->GetIP()))
str.AppendFormat(_T("IP=%s"), ipstr(sockAddr.sin_addr));
if (client){
if (!str.IsEmpty())
str += _T("; ");
str += _T("client=") + client->DbgGetClientInfo();
}
return str;
}
void CClientReqSocket::DbgAppendClientInfo(CString& str)
{
CString strClientInfo(DbgGetClientInfo());
if (!strClientInfo.IsEmpty()){
if (!str.IsEmpty())
str += _T("; ");
str += strClientInfo;
}
}
void CClientReqSocket::OnInit(){
//uint8 tv = 1;
//SetSockOpt(SO_DONTLINGER,&tv,sizeof(BOOL));
}
void CClientReqSocket::OnConnect(int nErrorCode)
{
CEMSocket::OnConnect(nErrorCode);
if (nErrorCode)
{
CString strTCPError;
if (thePrefs.GetVerbose())
{
strTCPError = GetErrorMessage(nErrorCode, 1);
if (nErrorCode != WSAECONNREFUSED && nErrorCode != WSAETIMEDOUT)
AddDebugLogLine(false, _T("Client TCP socket error (OnConnect): %s; %s"), strTCPError, DbgGetClientInfo());
}
}
}
void CClientReqSocket::OnSend(int nErrorCode){
ResetTimeOutTimer();
CEMSocket::OnSend(nErrorCode);
}
void CClientReqSocket::OnError(int nErrorCode)
{
CString strTCPError;
if (thePrefs.GetVerbose())
{
if (nErrorCode == ERR_WRONGHEADER)
strTCPError = _T("Wrong header");
else if (nErrorCode == ERR_TOOBIG)
strTCPError = _T("Too much data sent");
else
strTCPError = GetErrorMessage(nErrorCode);
AddDebugLogLine(false, _T("Client TCP socket error: %s; %s"), strTCPError, DbgGetClientInfo());
}
Disconnect(strTCPError);
}
bool CClientReqSocket::PacketReceivedCppEH(Packet* packet)
{
bool bResult;
UINT uRawSize = packet->size;
switch (packet->prot){
case OP_EDONKEYPROT:
bResult = ProcessPacket(packet->pBuffer,packet->size,packet->opcode);
break;
case OP_PACKEDPROT:
if (!packet->UnPackPacket()){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to decompress client TCP packet; %s; %s"), DbgGetClientTCPPacket(packet->prot, packet->opcode, packet->size), DbgGetClientInfo());
bResult = false;
break;
}
case OP_EMULEPROT:
bResult = ProcessExtPacket(packet->pBuffer, packet->size, packet->opcode, uRawSize);
break;
default:{
theStats.AddDownDataOverheadOther(uRawSize);
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Received unknown client TCP packet; %s; %s"), DbgGetClientTCPPacket(packet->prot, packet->opcode, packet->size), DbgGetClientInfo());
if (client)
client->SetDownloadState(DS_ERROR);
Disconnect(_T("Unknown protocol"));
bResult = false;
}
}
return bResult;
}
#ifdef USE_CLIENT_TCP_CATCH_ALL_HANDLER
int FilterSE(DWORD dwExCode, LPEXCEPTION_POINTERS pExPtrs, CClientReqSocket* reqsock, Packet* packet)
{
if (thePrefs.GetVerbose())
{
CString strExError;
if (pExPtrs){
const EXCEPTION_RECORD* er = pExPtrs->ExceptionRecord;
strExError.Format(_T("Error: Unknown exception %08x in CClientReqSocket::PacketReceived at 0x%08x"), er->ExceptionCode, er->ExceptionAddress);
}
else
strExError.Format(_T("Error: Unknown exception %08x in CClientReqSocket::PacketReceived"), dwExCode);
// we already had an unknown exception, better be prepared for dealing with invalid data -> use another exception handler
try{
CString strError = strExError;
strError.AppendFormat(_T("; %s"), DbgGetClientTCPPacket(packet?packet->prot:0, packet?packet->opcode:0, packet?packet->size:0));
reqsock->DbgAppendClientInfo(strError);
CemuleApp::AddDebugLogLine(false, _T("%s"), strError);
}
catch(...){
ASSERT(0);
CemuleApp::AddDebugLogLine(false, _T("%s"), strExError);
}
}
// this searches the next exception handler -> catch(...) in 'CAsyncSocketExHelperWindow::WindowProc'
// as long as I do not know where and why we are crashing, I prefere to have it handled that way which
// worked fine in 28a/b.
//
// 03-J鋘-2004 [bc]: Returning the execution to the catch-all handler in 'CAsyncSocketExHelperWindow::WindowProc'
// can make things even worse, because in some situations, the socket will continue fireing received events. And
// because the processed packet (which has thrown the exception) was not removed from the EMSocket buffers, it would
// be processed again and again.
//return EXCEPTION_CONTINUE_SEARCH;
// this would continue the program "as usual" -> return execution to the '__except' handler
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
#ifdef USE_CLIENT_TCP_CATCH_ALL_HANDLER
int CClientReqSocket::PacketReceivedSEH(Packet* packet)
{
int iResult;
// this function is only here to get a chance of determining the crash address via SEH
__try{
iResult = PacketReceivedCppEH(packet);
}
__except(FilterSE(GetExceptionCode(), GetExceptionInformation(), this, packet)){
iResult = -1;
}
return iResult;
}
#endif
bool CClientReqSocket::PacketReceived(Packet* packet)
{
bool bResult;
#ifdef USE_CLIENT_TCP_CATCH_ALL_HANDLER
int iResult = PacketReceivedSEH(packet);
if (iResult < 0)
{
if (client)
client->SetDownloadState(DS_ERROR);
Disconnect(_T("Unknown Exception"));
bResult = false;
}
else
bResult = (bool)iResult;
#else
bResult = PacketReceivedCppEH(packet);
#endif
return bResult;
}
void CClientReqSocket::OnReceive(int nErrorCode){
ResetTimeOutTimer();
CEMSocket::OnReceive(nErrorCode);
}
bool CClientReqSocket::Create(){
theApp.listensocket->AddConnection();
BOOL result = CAsyncSocketEx::Create(0,SOCK_STREAM,FD_WRITE|FD_READ|FD_CLOSE|FD_CONNECT); // deadlake PROXYSUPPORT - changed to AsyncSocketEx
OnInit();
return result;
}
SocketSentBytes CClientReqSocket::Send(uint32 maxNumberOfBytesToSend, uint32 overchargeMaxBytesToSend, bool onlyAllowedToSendControlPacket) {
SocketSentBytes returnStatus = CEMSocket::Send(maxNumberOfBytesToSend, overchargeMaxBytesToSend, onlyAllowedToSendControlPacket);
if(returnStatus.success && (returnStatus.sentBytesControlPackets > 0 || returnStatus.sentBytesStandardPackets > 0)) {
ResetTimeOutTimer();
}
return returnStatus;
}
// ZZ is this needed?
void CClientReqSocket::SendPacket(Packet* packet, bool delpacket, bool controlpacket, uint32 actualPayloadSize){
ResetTimeOutTimer();
CEMSocket::SendPacket(packet,delpacket,controlpacket, actualPayloadSize);
}
// CListenSocket
// CListenSocket member functions
CListenSocket::CListenSocket()
{
bListening = false;
opensockets = 0;
maxconnectionreached = 0;
m_OpenSocketsInterval = 0;
m_nPendingConnections = 0;
memset(m_ConnectionStates, 0, sizeof m_ConnectionStates);
peakconnections = 0;
totalconnectionchecks = 0;
averageconnections = 0.0;
activeconnections = 0;
}
CListenSocket::~CListenSocket(){
Close();
KillAllSockets();
}
bool CListenSocket::StartListening(){
bListening = true;
// Creating the socket with SO_REUSEADDR may solve LowID issues if emule was restarted
// quickly or started after a crash, but(!) it will also create another problem. If the
// socket is already used by some other application (e.g. a 2nd emule), we though bind
// to that socket leading to the situation that 2 applications are listening at the same
// port!
return (Create(thePrefs.GetPort(), SOCK_STREAM, FD_ACCEPT, NULL, FALSE/*TRUE*/) && Listen());
}
void CListenSocket::ReStartListening(){
bListening = true;
if (m_nPendingConnections){
m_nPendingConnections--;
OnAccept(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -