bool CUpDownClient::ProcessPeerCacheAcknowledge(const uchar* packet, UINT size) { const bool bDebug = (thePrefs.GetDebugClientTCPLevel() > 0); if (bDebug) DebugRecv("OP_PeerCacheAck", this); if (socket == NULL){ ASSERT(0); return false; } m_bPeerCacheUpHit = false; CSafeMemFile data(packet, size); UINT uAck = data.ReadUInt8(); if (uAck == 1) { // Cache hit if (bDebug) Debug(_T(" Cache hit\n")); // PC-TODO: If this socket is closed, PeerCache also closes the socket which it had opened to the // remote client! So, to give the remote client a chance to receive all the data from the PeerCache, // we have to keep this socket open, although it's not needed nor could it be reused! if (m_pPCUpSocket == NULL){ if (thePrefs.GetVerbose()) DebugLogError(_T("PeerCacheAck received - missing socket; %s"), DbgGetClientInfo()); ASSERT(0); return false; } // m_pPCUpSocket->Safe_Delete(); // m_pPCUpSocket = NULL; m_pPCUpSocket->SetTimeOut(MIN2MS(60)); // set socket timeout to 1 hour ?? m_bPeerCacheUpHit = true; } else if (uAck == 0) { // Cache miss, keep uploading if (bDebug) Debug(_T(" Cache miss\n")); } else{ ASSERT(0); return false; } // PC-TODO: Since we can not close the PC socket, what exactly do we need this ACK-packet for? ; UpdateDisplayedInfo(); return true; }
bool CUpDownClient::ProcessPeerCacheQuery(const uchar* packet, UINT size) { const bool bDebug = (thePrefs.GetDebugClientTCPLevel() > 0); if (bDebug) DebugRecv("OP_PeerCacheQuery", this); if (socket == NULL){ ASSERT(0); return false; } CSafeMemFile dataRecv(packet, size); uint8 uPCVersion = dataRecv.ReadUInt8(); if (uPCVersion != PCPCK_VERSION){ if (bDebug) Debug(_T(" ***Invalid packet version: 0x%02x\n"), uPCVersion); ASSERT(0); return false; } uint8 uPCOpcode = dataRecv.ReadUInt8(); if (uPCOpcode != PCOP_REQ){ if (bDebug) Debug(_T(" ***Invalid packet opcode: 0x%02x\n"), uPCOpcode); ASSERT(0); return false; } uint32 uCacheIP = 0; uint16 uCachePort = 0; uint32 uPushId = 0; uchar aucFileHash[16]; uint32 uRemoteIP = 0; md4clr(aucFileHash); CString strInfo; UINT uTags = dataRecv.ReadUInt8(); while (uTags--) { CTag tag(&dataRecv, GetUnicodeSupport()!=utf8strNone); if (tag.GetNameID() == PCTAG_CACHEIP && tag.IsInt()) { uCacheIP = tag.GetInt(); if (bDebug) strInfo.AppendFormat(_T(" CacheIP=%s"), ipstr(uCacheIP)); } else if (tag.GetNameID() == PCTAG_CACHEPORT && tag.IsInt()) { uCachePort = (uint16)tag.GetInt(); if (bDebug) strInfo.AppendFormat(_T(" CachePort=%u"), uCachePort); } else if (tag.GetNameID() == PCTAG_PUSHID && tag.IsInt()) { uPushId = tag.GetInt(); if (bDebug) strInfo.AppendFormat(_T(" PushId=%u"), uPushId); } else if (tag.GetNameID() == PCTAG_FILEID && tag.IsHash() && tag.GetHash() != NULL) { md4cpy(aucFileHash, tag.GetHash()); if (bDebug) strInfo.AppendFormat(_T(" FileId=%s"), md4str(aucFileHash)); } else if (tag.GetNameID() == PCTAG_PUBLICIP && tag.IsInt()) { uRemoteIP = tag.GetInt(); if (bDebug) strInfo.AppendFormat(_T(" PublicIP=%s"), ipstr(uRemoteIP)); } else { if (bDebug) strInfo.AppendFormat(_T(" ***UnkTag: %s"), tag.GetFullInfo()); ASSERT(0); } } if (bDebug) { if (dataRecv.GetPosition() < dataRecv.GetLength()) strInfo.AppendFormat(_T(" ***AddData: %u bytes"), (UINT)(dataRecv.GetLength() - dataRecv.GetPosition())); Debug(_T("%s\n"), strInfo); } if (uCacheIP == 0 || uCachePort == 0 || uPushId == 0 || isnulmd4(aucFileHash)){ if (thePrefs.GetVerbose()) AddDebugLogLine(false, _T("Invalid PeerCacheQuery; %s"), DbgGetClientInfo()); return false; } CKnownFile* pUploadFile = theApp.sharedfiles->GetFileByID(aucFileHash); if (pUploadFile == NULL){ if (thePrefs.GetVerbose()) AddDebugLogLine(false, _T("PeerCacheQuery reqfile does not match ed2k reqfile; %s"), DbgGetClientInfo()); return false; } if (m_pPCUpSocket != NULL) { SetPeerCacheUpState(PCUS_NONE); m_pPCUpSocket->Safe_Delete(); ASSERT( m_pPCUpSocket == NULL ); } m_pPCUpSocket = new CPeerCacheUpSocket(this); m_pPCUpSocket->SetTimeOut(GetPeerCacheSocketUploadTimeout()); m_pPCUpSocket->Create(); SOCKADDR_IN sockAddr = {0}; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(uCachePort); sockAddr.sin_addr.S_un.S_addr = uCacheIP; //Try to always tell the socket to WaitForOnConnect before you call Connect. m_pPCUpSocket->WaitForOnConnect(); m_pPCUpSocket->Connect((SOCKADDR*)&sockAddr, sizeof sockAddr); CStringA strPCRequest; strPCRequest.AppendFormat("GIVE %u\r\n", uPushId); if (thePrefs.GetDebugClientTCPLevel() > 0){ DebugSend("PeerCache-GIVE", this, pUploadFile->GetFileHash()); Debug(_T(" %hs\n"), strPCRequest); } CRawPacket* pHttpPacket = new CRawPacket(strPCRequest); theStats.AddUpDataOverheadFileRequest(pHttpPacket->size); m_pPCUpSocket->SendPacket(pHttpPacket); m_pPCUpSocket->SetHttpState(HttpStateRecvExpected); m_bPeerCacheUpHit = false; SetPeerCacheUpState(PCUS_WAIT_CACHE_REPLY); //theApp.uploadBandwidthThrottler->AddToStandardList(0, m_pPCUpSocket); CSafeMemFile dataSend(128); dataSend.WriteUInt8(PCPCK_VERSION); dataSend.WriteUInt8(PCOP_RES); dataSend.WriteUInt8(3); CTag tagPushId(PCTAG_PUSHID, uPushId); tagPushId.WriteNewEd2kTag(&dataSend); CTag tagPublicIP(PCTAG_PUBLICIP, theApp.GetPublicIP()); tagPublicIP.WriteNewEd2kTag(&dataSend); CTag tagFileId(PCTAG_FILEID, (BYTE*)aucFileHash); tagFileId.WriteNewEd2kTag(&dataSend); if (thePrefs.GetDebugClientTCPLevel() > 0){ DebugSend("OP__PeerCacheAnswer", this, aucFileHash); Debug(_T(" PushId=%u PublicIP=%s FileId=%s\n"), tagPushId.GetInt(), ipstr(tagPublicIP.GetInt()), md4str(tagFileId.GetHash())); } Packet* pEd2kPacket = new Packet(&dataSend, OP_EMULEPROT, OP_PEERCACHE_ANSWER); theStats.AddUpDataOverheadFileRequest(pEd2kPacket->size); socket->SendPacket(pEd2kPacket); return true; }
bool CUpDownClient::ProcessPeerCacheAnswer(const uchar* packet, UINT size) { const bool bDebug = (thePrefs.GetDebugClientTCPLevel() > 0); ASSERT( GetDownloadState() == DS_DOWNLOADING ); ASSERT( m_ePeerCacheDownState == PCDS_WAIT_CLIENT_REPLY ); if (bDebug) DebugRecv("OP_PeerCacheAnswer", this); if (socket == NULL || reqfile == NULL){ ASSERT(0); return false; } CSafeMemFile dataRecv(packet, size); uint8 uPCVersion = dataRecv.ReadUInt8(); if (uPCVersion != PCPCK_VERSION){ if (bDebug) Debug(_T(" ***Invalid packet version: 0x%02x\n"), uPCVersion); ASSERT(0); return false; } uint8 uPCOpcode = dataRecv.ReadUInt8(); if (uPCOpcode == PCOP_NONE){ if (thePrefs.GetVerbose()) AddDebugLogLine(false, _T("Client does not support PeerCache; %s"), DbgGetClientInfo()); return false; } if (uPCOpcode != PCOP_RES){ if (bDebug) Debug(_T(" ***Invalid packet opcode: 0x%02x\n"), uPCOpcode); ASSERT(0); return false; } uint32 uPushId = 0; uint32 uRemoteIP = 0; uchar aucFileHash[16]; md4clr(aucFileHash); CString strInfo; UINT uTags = dataRecv.ReadUInt8(); while (uTags--) { CTag tag(&dataRecv, GetUnicodeSupport()!=utf8strNone); if (tag.GetNameID() == PCTAG_PUSHID && tag.IsInt()) { uPushId = tag.GetInt(); if (bDebug) strInfo.AppendFormat(_T(" PushId=%u"), uPushId); } else if (tag.GetNameID() == PCTAG_PUBLICIP && tag.IsInt()) { uRemoteIP = tag.GetInt(); if (bDebug) strInfo.AppendFormat(_T(" RemoteIP=%s"), ipstr(uRemoteIP)); } else if (tag.GetNameID() == PCTAG_FILEID && tag.IsHash() && tag.GetHash() != NULL) { md4cpy(aucFileHash, tag.GetHash()); if (bDebug) strInfo.AppendFormat(_T(" FileId=%s"), md4str(aucFileHash)); } else { if (bDebug) strInfo.AppendFormat(_T(" ***UnkTag: %s"), tag.GetFullInfo()); ASSERT(0); } } if (bDebug) { if (dataRecv.GetPosition() < dataRecv.GetLength()) strInfo.AppendFormat(_T(" ***AddData: %u bytes"), (UINT)(dataRecv.GetLength() - dataRecv.GetPosition())); Debug(_T("%s\n"), strInfo); } if (uPushId == 0 || uRemoteIP == 0 || isnulmd4(aucFileHash)){ if (thePrefs.GetVerbose()) AddDebugLogLine(false, _T("Invalid PeerCacheAnswer; %s"), DbgGetClientInfo()); return false; } if (md4cmp(aucFileHash, reqfile->GetFileHash()) != 0){ if (thePrefs.GetVerbose()) AddDebugLogLine(false, _T("PeerCacheAnswer reqfile does not match ed2k reqfile; %s"), DbgGetClientInfo()); return false; } m_uPeerCacheDownloadPushId = uPushId; m_uPeerCacheRemoteIP = uRemoteIP; if (!SendHttpBlockRequests()) return false; theApp.m_pPeerCache->DownloadAttemptStarted(); ASSERT( m_ePeerCacheDownState == PCDS_WAIT_CACHE_REPLY ); return true; }
bool CClientUDPSocket::ProcessPacket(const BYTE* packet, uint16 size, uint8 opcode, uint32 ip, uint16 port) { switch(opcode) { case OP_REASKCALLBACKUDP: { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskCallbackUDP", NULL, NULL, ip); theStats.AddDownDataOverheadOther(size); CUpDownClient* buddy = theApp.clientlist->GetBuddy(); if( buddy ) { if( size < 17 || buddy->socket == NULL ) break; if (!md4cmp(packet, buddy->GetBuddyID())) { PokeUInt32(const_cast<BYTE*>(packet)+10, ip); PokeUInt16(const_cast<BYTE*>(packet)+14, port); Packet* response = new Packet(OP_EMULEPROT); response->opcode = OP_REASKCALLBACKTCP; response->pBuffer = new char[size]; memcpy(response->pBuffer, packet+10, size-10); response->size = size-10; if (thePrefs.GetDebugClientTCPLevel() > 0) DebugSend("OP__ReaskCallbackTCP", buddy); theStats.AddUpDataOverheadFileRequest(response->size); buddy->socket->SendPacket(response); } } break; } case OP_REASKFILEPING: { theStats.AddDownDataOverheadFileRequest(size); CSafeMemFile data_in(packet, size); uchar reqfilehash[16]; data_in.ReadHash16(reqfilehash); CKnownFile* reqfile = theApp.sharedfiles->GetFileByID(reqfilehash); if (!reqfile) { if (thePrefs.GetDebugClientUDPLevel() > 0) { DebugRecv("OP_ReaskFilePing", NULL, reqfilehash, ip); DebugSend("OP__FileNotFound", NULL); } Packet* response = new Packet(OP_FILENOTFOUND,0,OP_EMULEPROT); theStats.AddUpDataOverheadFileRequest(response->size); SendPacket(response, ip, port); break; } CUpDownClient* sender = theApp.uploadqueue->GetWaitingClientByIP_UDP(ip, port); if (sender) { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskFilePing", sender, reqfilehash); //Make sure we are still thinking about the same file if (md4cmp(reqfilehash, sender->GetUploadFileID()) == 0) { sender->AddAskedCount(); sender->SetLastUpRequest(); //I messed up when I first added extended info to UDP //I should have originally used the entire ProcessExtenedInfo the first time. //So now I am forced to check UDPVersion to see if we are sending all the extended info. //For now on, we should not have to change anything here if we change //anything to the extended info data as this will be taken care of in ProcessExtendedInfo() //Update extended info. if (sender->GetUDPVersion() > 3) { sender->ProcessExtendedInfo(&data_in, reqfile); } //Update our complete source counts. else if (sender->GetUDPVersion() > 2) { uint16 nCompleteCountLast= sender->GetUpCompleteSourcesCount(); uint16 nCompleteCountNew = data_in.ReadUInt16(); sender->SetUpCompleteSourcesCount(nCompleteCountNew); if (nCompleteCountLast != nCompleteCountNew) { reqfile->UpdatePartsInfo(); } } CSafeMemFile data_out(128); if(sender->GetUDPVersion() > 3) { if (reqfile->IsPartFile()) ((CPartFile*)reqfile)->WritePartStatus(&data_out); else data_out.WriteUInt16(0); } data_out.WriteUInt16(theApp.uploadqueue->GetWaitingPosition(sender)); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugSend("OP__ReaskAck", sender); Packet* response = new Packet(&data_out, OP_EMULEPROT); response->opcode = OP_REASKACK; theStats.AddUpDataOverheadFileRequest(response->size); theApp.clientudp->SendPacket(response, ip, port); } else { DebugLogError(_T("Client UDP socket; ReaskFilePing; reqfile does not match")); TRACE(_T("reqfile: %s\n"), DbgGetFileInfo(reqfile->GetFileHash())); TRACE(_T("sender->GetRequestFile(): %s\n"), sender->GetRequestFile() ? DbgGetFileInfo(sender->GetRequestFile()->GetFileHash()) : _T("(null)")); } } else { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskFilePing", NULL, reqfilehash, ip); if (((uint32)theApp.uploadqueue->GetWaitingUserCount() + 50) > thePrefs.GetQueueSize()) { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugSend("OP__QueueFull", NULL); Packet* response = new Packet(OP_QUEUEFULL,0,OP_EMULEPROT); theStats.AddUpDataOverheadFileRequest(response->size); SendPacket(response, ip, port); } } break; } case OP_QUEUEFULL: { theStats.AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_QueueFull", sender, NULL, ip); if (sender){ sender->SetRemoteQueueFull(true); sender->UDPReaskACK(0); } break; } case OP_REASKACK: { theStats.AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskAck", sender, NULL, ip); if (sender){ CSafeMemFile data_in(packet, size); if ( sender->GetUDPVersion() > 3 ) { sender->ProcessFileStatus(true, &data_in, sender->GetRequestFile()); } uint16 nRank = data_in.ReadUInt16(); sender->SetRemoteQueueFull(false); sender->UDPReaskACK(nRank); sender->AddAskedCountDown(); } break; } case OP_FILENOTFOUND: { theStats.AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_FileNotFound", sender, NULL, ip); if (sender){ sender->UDPReaskFNF(); // may delete 'sender'! sender = NULL; } break; } case OP_PORTTEST: { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_PortTest", NULL, NULL, ip); theStats.AddDownDataOverheadOther(size); if (size == 1){ if (packet[0] == 0x12){ bool ret = theApp.listensocket->SendPortTestReply('1', true); AddDebugLogLine(true, _T("UDP Portcheck packet arrived - ACK sent back (status=%i)"), ret); } } break; } default: theStats.AddDownDataOverheadOther(size); if (thePrefs.GetDebugClientUDPLevel() > 0) { CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); Debug(_T("Unknown client UDP packet: host=%s:%u (%s) opcode=0x%02x size=%u\n"), ipstr(ip), port, sender ? sender->DbgGetClientInfo() : _T(""), opcode, size); } return false; } return true; }