📄 downloadqueue.cpp
字号:
CString fullname = newfile->GetFileName();
fullname.MakeLower();
CString cmpExt = catExt.Tokenize(_T("|"), curPos);
while (!cmpExt.IsEmpty()) {
// HoaX_69: Allow wildcards in autocat string
// thanks to: bluecow, khaos and SlugFiller
if(cmpExt.Find(_T("*")) != -1 || cmpExt.Find(_T("?")) != -1){
// Use wildcards
if(PathMatchSpec(fullname, cmpExt)){
newfile->SetCategory(ix);
return;
}
}else{
if(fullname.Find(cmpExt) != -1){
newfile->SetCategory(ix);
return;
}
}
cmpExt = catExt.Tokenize(_T("|"),curPos);
}
}
}
}
// HoaX_69: END
void CDownloadQueue::ResetLocalServerRequests()
{
m_dwNextTCPSrcReq = 0;
m_localServerReqQueue.RemoveAll();
POSITION pos = filelist.GetHeadPosition();
while (pos != NULL)
{
CPartFile* pFile = filelist.GetNext(pos);
UINT uState = pFile->GetStatus();
if (uState == PS_READY || uState == PS_EMPTY)
pFile->ResumeFile();
pFile->m_bLocalSrcReqQueued = false;
}
}
void CDownloadQueue::RemoveLocalServerRequest(CPartFile* pFile)
{
POSITION pos1, pos2;
for( pos1 = m_localServerReqQueue.GetHeadPosition(); ( pos2 = pos1 ) != NULL; )
{
m_localServerReqQueue.GetNext(pos1);
if (m_localServerReqQueue.GetAt(pos2) == pFile)
{
m_localServerReqQueue.RemoveAt(pos2);
pFile->m_bLocalSrcReqQueued = false;
// could 'break' here.. fail safe: go through entire list..
}
}
}
void CDownloadQueue::ProcessLocalRequests()
{
if ( (!m_localServerReqQueue.IsEmpty()) && (m_dwNextTCPSrcReq < ::GetTickCount()) )
{
CSafeMemFile dataTcpFrame(22);
const int iMaxFilesPerTcpFrame = 15;
int iFiles = 0;
while (!m_localServerReqQueue.IsEmpty() && iFiles < iMaxFilesPerTcpFrame)
{
// find the file with the longest waitingtime
POSITION pos1, pos2;
uint32 dwBestWaitTime = 0xFFFFFFFF;
POSITION posNextRequest = NULL;
CPartFile* cur_file;
for( pos1 = m_localServerReqQueue.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){
m_localServerReqQueue.GetNext(pos1);
cur_file = m_localServerReqQueue.GetAt(pos2);
if (cur_file->GetStatus() == PS_READY || cur_file->GetStatus() == PS_EMPTY)
{
uint8 nPriority = cur_file->GetDownPriority();
if (nPriority > PR_HIGH){
ASSERT(0);
nPriority = PR_HIGH;
}
if (cur_file->lastsearchtime + (PR_HIGH-nPriority) < dwBestWaitTime ){
dwBestWaitTime = cur_file->lastsearchtime + (PR_HIGH-nPriority);
posNextRequest = pos2;
}
}
else{
m_localServerReqQueue.RemoveAt(pos2);
cur_file->m_bLocalSrcReqQueued = false;
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("SXSend: Local server source request for file \"%s\" not sent because of status '%s'"), cur_file->GetFileName(), cur_file->getPartfileStatus());
}
}
if (posNextRequest != NULL)
{
cur_file = m_localServerReqQueue.GetAt(posNextRequest);
cur_file->m_bLocalSrcReqQueued = false;
cur_file->lastsearchtime = ::GetTickCount();
m_localServerReqQueue.RemoveAt(posNextRequest);
iFiles++;
// create request packet
Packet* packet = new Packet(OP_GETSOURCES,16);
md4cpy(packet->pBuffer,cur_file->GetFileHash());
if (thePrefs.GetDebugServerTCPLevel() > 0)
Debug(_T(">>> Sending OP__GetSources(%2u/%2u); %s\n"), iFiles, iMaxFilesPerTcpFrame, DbgGetFileInfo(cur_file->GetFileHash()));
dataTcpFrame.Write(packet->GetPacket(), packet->GetRealPacketSize());
delete packet;
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("SXSend: Local server source request; File=\"%s\""), cur_file->GetFileName());
}
}
int iSize = dataTcpFrame.GetLength();
if (iSize > 0)
{
// create one 'packet' which contains all buffered OP_GETSOURCES eD2K packets to be sent with one TCP frame
// server credits: 16*iMaxFilesPerTcpFrame+1 = 241
Packet* packet = new Packet(new char[iSize], dataTcpFrame.GetLength(), true, false);
dataTcpFrame.Seek(0, CFile::begin);
dataTcpFrame.Read(packet->GetPacket(), iSize);
theStats.AddUpDataOverheadServer(packet->size);
theApp.serverconnect->SendPacket(packet, true);
}
// next TCP frame with up to 15 source requests is allowed to be sent in..
m_dwNextTCPSrcReq = ::GetTickCount() + SEC2MS(iMaxFilesPerTcpFrame*(16+4));
}
}
void CDownloadQueue::SendLocalSrcRequest(CPartFile* sender){
ASSERT ( !m_localServerReqQueue.Find(sender) );
m_localServerReqQueue.AddTail(sender);
}
void CDownloadQueue::GetDownloadStats(int results[],
uint64& rui64TotFileSize,
uint64& rui64TotBytesLeftToTransfer,
uint64& rui64TotNeededSpace)
{
results[0] = 0;
results[1] = 0;
results[2] = 0;
for (POSITION pos = filelist.GetHeadPosition();pos != 0; )
{
const CPartFile* cur_file = filelist.GetNext(pos);
UINT uState = cur_file->GetStatus();
if (uState == PS_READY || uState == PS_EMPTY)
{
uint32 ui32SizeToTransfer = 0;
uint32 ui32NeededSpace = 0;
cur_file->GetSizeToTransferAndNeededSpace(ui32SizeToTransfer, ui32NeededSpace);
rui64TotFileSize += cur_file->GetFileSize();
rui64TotBytesLeftToTransfer += ui32SizeToTransfer;
rui64TotNeededSpace += ui32NeededSpace;
results[2]++;
}
results[0] += cur_file->GetSourceCount();
results[1] += cur_file->GetTransferingSrcCount();
}
}
///////////////////////////////////////////////////////////////////////////////
// CSourceHostnameResolveWnd
BEGIN_MESSAGE_MAP(CSourceHostnameResolveWnd, CWnd)
ON_MESSAGE(WM_HOSTNAMERESOLVED, OnHostnameResolved)
END_MESSAGE_MAP()
CSourceHostnameResolveWnd::CSourceHostnameResolveWnd()
{
}
CSourceHostnameResolveWnd::~CSourceHostnameResolveWnd()
{
while (!m_toresolve.IsEmpty())
delete m_toresolve.RemoveHead();
}
void CSourceHostnameResolveWnd::AddToResolve(const uchar* fileid, LPCSTR pszHostname, uint16 port, LPCTSTR pszURL)
{
bool bResolving = !m_toresolve.IsEmpty();
// double checking
if (!theApp.downloadqueue->GetFileByID(fileid))
return;
Hostname_Entry* entry = new Hostname_Entry;
md4cpy(entry->fileid, fileid);
entry->strHostname = pszHostname;
entry->port = port;
entry->strURL = pszURL;
m_toresolve.AddTail(entry);
if (bResolving)
return;
memset(m_aucHostnameBuffer, 0, sizeof(m_aucHostnameBuffer));
if (WSAAsyncGetHostByName(m_hWnd, WM_HOSTNAMERESOLVED, entry->strHostname, m_aucHostnameBuffer, sizeof m_aucHostnameBuffer) != 0)
return;
m_toresolve.RemoveHead();
delete entry;
}
LRESULT CSourceHostnameResolveWnd::OnHostnameResolved(WPARAM wParam,LPARAM lParam)
{
if (m_toresolve.IsEmpty())
return TRUE;
Hostname_Entry* resolved = m_toresolve.RemoveHead();
if (WSAGETASYNCERROR(lParam) == 0)
{
int iBufLen = WSAGETASYNCBUFLEN(lParam);
if (iBufLen >= sizeof(HOSTENT))
{
LPHOSTENT pHost = (LPHOSTENT)m_aucHostnameBuffer;
if (pHost->h_length == 4 && pHost->h_addr_list && pHost->h_addr_list[0])
{
uint32 nIP = ((LPIN_ADDR)(pHost->h_addr_list[0]))->s_addr;
CPartFile* file = theApp.downloadqueue->GetFileByID(resolved->fileid);
if (file)
{
if (resolved->strURL.IsEmpty())
{
CSafeMemFile sources(1+4+2);
sources.WriteUInt8(1);
sources.WriteUInt32(nIP);
sources.WriteUInt16(resolved->port);
sources.SeekToBegin();
file->AddSources(&sources,0,0);
}
else
{
file->AddSource(resolved->strURL, nIP);
}
}
}
}
}
delete resolved;
while (!m_toresolve.IsEmpty())
{
Hostname_Entry* entry = m_toresolve.GetHead();
memset(m_aucHostnameBuffer, 0, sizeof(m_aucHostnameBuffer));
if (WSAAsyncGetHostByName(m_hWnd, WM_HOSTNAMERESOLVED, entry->strHostname, m_aucHostnameBuffer, sizeof m_aucHostnameBuffer) != 0)
return TRUE;
m_toresolve.RemoveHead();
delete entry;
}
return TRUE;
}
bool CDownloadQueue::DoKademliaFileRequest()
{
return ((::GetTickCount() - lastkademliafilerequest) > KADEMLIAASKTIME);
}
void CDownloadQueue::KademliaSearchFile(uint32 searchID, const Kademlia::CUInt128* pcontactID, const Kademlia::CUInt128* pbuddyID, uint8 type, uint32 ip, uint16 tcp, uint16 udp, uint32 serverip, uint16 serverport, uint32 clientid)
{
//Safty measure to make sure we are looking for these sources
CPartFile* temp = GetFileByKadFileSearchID(searchID);
if( !temp )
return;
//Do we need more sources?
if(!(!temp->IsStopped() && thePrefs.GetMaxSourcePerFile() > temp->GetSourceCount()))
return;
uint32 ED2Kip = ntohl(ip);
if (theApp.ipfilter->IsFiltered(ED2Kip))
{
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("IPfiltered source IP=%s (%s) received from Kademlia"), ipstr(ED2Kip), theApp.ipfilter->GetLastHit());
return;
}
if( (ip == Kademlia::CKademlia::getIPAddress() || ED2Kip == theApp.serverconnect->GetClientID()) && tcp == thePrefs.GetPort())
return;
CUpDownClient* ctemp = NULL;
switch( type )
{
case 1:
{
//NonFirewalled users
if(!tcp)
{
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received from Kademlia, no tcp port received"), ipstr(ip));
return;
}
if (!IsGoodIP(ED2Kip))
{
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received from Kademlia"), ipstr(ED2Kip));
return;
}
ctemp = new CUpDownClient(temp,tcp,ip,0,0,false);
ctemp->SetSourceFrom(SF_KADEMLIA);
ctemp->SetServerIP(serverip);
ctemp->SetServerPort(serverport);
ctemp->SetKadPort(udp);
byte cID[16];
pcontactID->toByteArray(cID);
ctemp->SetUserHash(cID);
break;
}
case 2:
{
//Don't use this type... Some clients will process it wrong..
break;
}
case 3:
{
//This will be a firewaled client connected to Kad only.
//We set the clientID to 1 as a Kad user only has 1 buddy.
ctemp = new CUpDownClient(temp,0,1,0,0,false);
//The only reason we set the real IP is for when we get a callback
//from this firewalled source, the compare method will match them.
ctemp->SetSourceFrom(SF_KADEMLIA);
ctemp->SetKadPort(udp);
byte cID[16];
pcontactID->toByteArray(cID);
ctemp->SetUserHash(cID);
pbuddyID->toByteArray(cID);
ctemp->SetBuddyID(cID);
ctemp->SetBuddyIP(serverip);
ctemp->SetBuddyPort(serverport);
break;
}
}
if (ctemp)
CheckAndAddSource(temp, ctemp);
}
void CDownloadQueue::ExportPartMetFilesOverview() const
{
CString strFileListPath = thePrefs.GetAppDir() + _T("downloads.txt");
CString strTmpFileListPath = strFileListPath;
PathRenameExtension(strTmpFileListPath.GetBuffer(MAX_PATH), _T(".tmp"));
strTmpFileListPath.ReleaseBuffer();
CSafeBufferedFile file;
CFileException fexp;
if (!file.Open(strTmpFileListPath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary | CFile::shareDenyWrite, &fexp))
{
CString strError;
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (fexp.GetErrorMessage(szError, ARRSIZE(szError))){
strError += _T(" - ");
strError += szError;
}
AddLogLine(false, _T("Failed to create part.met file list%s"), strError);
return;
}
#ifdef _UNICODE
// write Unicode byte-order mark 0xFEFF
fputwc(0xFEFF, file.m_pStream);
#endif
try
{
file.printf(_T("Date: %s\r\n"), CTime::GetCurrentTime().Format(_T("%c")));
file.printf(_T("Directory: %s\r\n"), thePrefs.GetTempDir());
file.printf(_T("\r\n"));
file.printf(_T("Part file\teD2K link\r\n"));
file.printf(_T("--------------------------------------------------------------------------------\r\n"));
for (POSITION pos = filelist.GetHeadPosition(); pos != 0; )
{
const CPartFile* pPartFile = filelist.GetNext(pos);
if (pPartFile->GetStatus(true) != PS_COMPLETE)
{
CString strPartFilePath(pPartFile->GetFilePath());
TCHAR szNam[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
_tsplitpath(strPartFilePath, NULL, NULL, szNam, szExt);
file.printf(_T("%s%s\t%s\r\n"), szNam, szExt, CreateED2kLink(pPartFile));
}
}
if (thePrefs.GetCommitFiles() >= 2 || (thePrefs.GetCommitFiles() >= 1 && !theApp.emuledlg->IsRunning())){
file.Flush(); // flush file stream buffers to disk buffers
if (_commit(_fileno(file.m_pStream)) != 0) // commit disk buffers to disk
AfxThrowFileException(CFileException::hardIO, GetLastError(), file.GetFileName());
}
file.Close();
CString strBakFileListPath = strFileListPath;
PathRenameExtension(strBakFileListPath.GetBuffer(MAX_PATH), _T(".bak"));
strBakFileListPath.ReleaseBuffer();
if (_taccess(strBakFileListPath, 0) == 0)
CFile::Remove(strBakFileListPath);
if (_taccess(strFileListPath, 0) == 0)
CFile::Rename(strFileListPath, strBakFileListPath);
CFile::Rename(strTmpFileListPath, strFileListPath);
}
catch(CFileException* e)
{
CString strError;
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (e->GetErrorMessage(szError, ARRSIZE(szError))){
strError += _T(" - ");
strError += szError;
}
AddLogLine(false, _T("Failed to write part.met file list%s"), strError);
e->Delete();
file.Abort();
(void)_tremove(file.GetFilePath());
}
}
void CDownloadQueue::OnConnectionState(bool bConnected)
{
for (POSITION pos = filelist.GetHeadPosition(); pos != 0; )
{
CPartFile* pPartFile = filelist.GetNext(pos);
if (pPartFile->IsPartFile())
pPartFile->SetActive(bConnected);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -