00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "fsInternetDownloader.h"
00008 #include "fsTicksMgr.h"
00009 #include "misc.h"
00010 #include "inetutil.h"
00011 #include <math.h>
00012 #include "fsArchiveInternetStream.h"
00013 #include "fsZipArchiveFastRebuilder.h"
00014 #include "fsArchiveFileStream.h"
00015 #include "vmsSpeedTracker.h"
00016 #include "vmsInternetSession.h"
00017
00018 using namespace fsArchive;
00019
00020 BOOL fsInternetDownloader::m_bPauseMode = FALSE;
00021 UINT64 fsInternetDownloader::m_nTotalTraffic = 0;
00022 fsSpeedMeter fsInternetDownloader::m_TotalSpeed;
00023 vmsCriticalSection fsInternetDownloader::m_csDataRcvd;
00024
00025 #ifdef _DEBUG
00026 #undef THIS_FILE
00027 static char THIS_FILE[]=__FILE__;
00028 #define new DEBUG_NEW
00029 #endif
00030
00031 #define TSECT(sect) ;
00032
00033 fsInternetDownloader::fsInternetDownloader()
00034 {
00035 ZeroMemory (DNP (), sizeof (m_dnp));
00036
00037 m_bErrDownloading = FALSE;
00038 m_uRetryTime = 5000;
00039
00040 m_hOutFile = INVALID_HANDLE_VALUE;
00041
00042 InitializeCriticalSection (&m_csWriteToFile);
00043 InitializeCriticalSection (&m_csAddSection);
00044
00045 m_uSectionMinSize = 20000;
00046 m_bNeedStop = FALSE;
00047 m_cThreads = m_cRunningThreads = 0;
00048 m_uTrafficLimit = UINT_MAX;
00049 m_pfnEvents = NULL;
00050 m_uMaxAttempts = UINT_MAX;
00051 m_bDontRestartIfNoRanges = FALSE;
00052
00053 m_pfnEvents = NULL;
00054
00055 m_pOpeningFile = NULL;
00056
00057 StopOnFileNotFound (TRUE);
00058 StopOnAccDenied (TRUE);
00059
00060 InitializeCriticalSection (&m_csDone);
00061 InitializeCriticalSection (&m_csOpenUrl);
00062 InitializeCriticalSection (&m_csSections);
00063
00064 m_enRST = RST_UNKNOWN;
00065 m_uSSFileSize = m_uLDFileSize = 0;
00066
00067 m_cBaseSectCreatingNow = 0;
00068
00069 m_bDetLog = FALSE;
00070
00071 m_pMirrURLMgr = NULL;
00072
00073 m_bSearchForMirrors = FALSE;
00074 m_bMirrMeasureSpeed = FALSE;
00075 m_uMirrFileMinSize = 1000*1024;
00076 m_dwBaseServerPingTime = UINT_MAX;
00077 m_dwState = 0;
00078 m_cMirrsFound = 0;
00079
00080 m_strContentType = "";
00081
00082 m_pZipPreviewStream = NULL;
00083 m_uTimeout = 120;
00084
00085 m_bAddingSection = FALSE;
00086
00087 ZeroMemory (&m_fileDate, sizeof (m_fileDate));
00088
00089 m_bWasAccessedAtLeastOnce = FALSE;
00090
00091 m_dwDataLenInCache = 0;
00092 m_dwForceCacheSizePerSection = DWORD (-1);
00093 }
00094
00095 fsInternetDownloader::~fsInternetDownloader()
00096 {
00097 StopDownloading ();
00098
00099 while (m_cThreads)
00100 Sleep (10);
00101
00102 DeleteCriticalSection (&m_csAddSection);
00103 DeleteCriticalSection (&m_csWriteToFile);
00104 DeleteCriticalSection (&m_csDone);
00105 DeleteCriticalSection (&m_csOpenUrl);
00106 DeleteCriticalSection (&m_csSections);
00107
00108 for (int i = 0; i < m_vMirrs.size (); i++)
00109 fsDNP_GetByUrl_Free (&m_vMirrs [i].dnp);
00110 }
00111
00112 fsDownload_NetworkProperties* fsInternetDownloader::DNP(int nSection)
00113 {
00114 if (nSection == -1)
00115 return &m_dnp;
00116
00117 return m_vSections [nSection].nMirrorURL == UINT_MAX ? &m_dnp :
00118 &m_vMirrs [m_vSections [nSection].nMirrorURL].dnp;
00119 }
00120
00121 fsInternetResult fsInternetDownloader::AddSection(BOOL bQueryCreation)
00122 {
00123 if (m_bErrDownloading)
00124 return IR_ERROR;
00125
00126 if (m_vSections.size ())
00127 return CreateAdditionalSection (bQueryCreation);
00128 else
00129 return CreateMainSection (bQueryCreation);
00130 }
00131
00132 fsInternetResult fsInternetDownloader::CreateMainSection(UINT uStartFrom, BOOL bQueryCreation)
00133 {
00134 fsSection sect;
00135
00136 fsInternetResult ir;
00137
00138 m_bNoNewSections = FALSE;
00139 m_bNeedStop = FALSE;
00140
00141 if (bQueryCreation && Event (DE_QUERYNEWSECTION, UINT_MAX) == FALSE)
00142 return IR_S_FALSE;
00143
00144 m_cBaseSectCreatingNow++;
00145 EnterCriticalSection (&m_csAddSection);
00146
00147 Event (DE_STARTINGDOWNLOAD);
00148
00149 Event (DE_STARTINGDOWNLOAD_CONNECTING);
00150
00151 UINT u = UINT_MAX;
00152 ir = OpenUrl (uStartFrom, §.file, -1, u);
00153
00154 if (ir != IR_SUCCESS)
00155 {
00156 m_cBaseSectCreatingNow--;
00157 LeaveCriticalSection (&m_csAddSection);
00158 Event (DE_STARTINGDOWNLOAD_FAILEDTOCONNECT);
00159 return ir;
00160 }
00161
00162 m_uSSFileSize = m_uLDFileSize = sect.file->GetFileSize ();
00163
00164 sect.uStart = sect.uDStart = 0;
00165 sect.uCurrent = sect.uDCurrent = uStartFrom;
00166 sect.uEnd = sect.uDEnd = GetSSFileSize ();
00167
00168 TSECT (§);
00169
00170 Auto_SearchMirrors ();
00171
00172
00173 if (FALSE == CreateSection (sect))
00174 {
00175 m_cBaseSectCreatingNow--;
00176 delete sect.file;
00177 LeaveCriticalSection (&m_csAddSection);
00178 return IR_S_FALSE;
00179 }
00180
00181 LeaveCriticalSection (&m_csAddSection);
00182
00183 return m_bNeedStop ? IR_S_FALSE : IR_SUCCESS;
00184 }
00185
00186 fsInternetResult fsInternetDownloader::CreateAdditionalSection(BOOL bQueryCreation)
00187 {
00188 if (m_bNoNewSections || m_bAddingSection)
00189 return IR_S_FALSE;
00190
00191 if (m_vSections.size () - GetDoneSectionCount () >= MAX_NOT_COMPLETED_SECTION_COUNT)
00192 return IR_S_FALSE;
00193
00194 if (GetSSFileSize () == _UI64_MAX)
00195 return IR_S_FALSE;
00196
00197 m_bAddingSection = TRUE;
00198
00199 UINT64 uMaxSection = 0;
00200 int iSection = -1;
00201 fsInternetResult ir;
00202
00203 if (IsMayZIP (TRUE) && m_vSections.size () == 1 &&
00204 m_vSections [0].uCurrent < ZIP_SFXMAXSIZE)
00205
00206 {
00207 m_bAddingSection = FALSE;
00208 return IR_S_FALSE;
00209 }
00210
00211 if (IsResumeSupported () == RST_NONE)
00212 {
00213 m_bAddingSection = FALSE;
00214 return IR_RANGESNOTAVAIL;
00215 }
00216
00217 EnterCriticalSection (&m_csAddSection);
00218
00219 fsSection sect;
00220 sect.nMirrorURL = FindNotBusyMirrorIndex ();
00221
00222 if (bQueryCreation && Event (DE_QUERYNEWSECTION, sect.nMirrorURL) == FALSE)
00223 {
00224 m_bAddingSection = FALSE;
00225 LeaveCriticalSection (&m_csAddSection);
00226 return IR_S_FALSE;
00227 }
00228
00229 UINT nMirrorInc = sect.nMirrorURL;
00230
00231 if (nMirrorInc == UINT_MAX)
00232 m_cBaseSectCreatingNow++;
00233 else
00234 m_vMirrs [nMirrorInc].cSectsCreatingNow ++;
00235
00236
00237 for (int i = 0; i < m_vSections.size (); i++)
00238 {
00239 if (m_vSections [i].state == SS_DONE)
00240 continue;
00241
00242 UINT64 uSection = m_vSections [i].uEnd - m_vSections [i].uCurrent;
00243
00244 if (uMaxSection < uSection)
00245 {
00246 uMaxSection = uSection;
00247 iSection = i;
00248 }
00249 }
00250
00251 if (iSection == -1 || uMaxSection/2 < m_uSectionMinSize || uMaxSection < 100*1024)
00252 {
00253 m_bAddingSection = FALSE;
00254 LeaveCriticalSection (&m_csAddSection);
00255 if (nMirrorInc == UINT_MAX)
00256 m_cBaseSectCreatingNow--;
00257 else
00258 m_vMirrs [nMirrorInc].cSectsCreatingNow --;
00259 return IR_S_FALSE;
00260 }
00261
00262 LOG ("creating new section in " << iSection << " section" << nl);
00263
00264 EnterCriticalSection (&m_csSections);
00265
00266 sect.uStart = sect.uCurrent = m_vSections [iSection].uCurrent + uMaxSection / 2;
00267 sect.uEnd = m_vSections [iSection].uEnd;
00268
00269 sect.uDStart = sect.uDCurrent = m_vSections [iSection].uDCurrent + uMaxSection / 2;
00270 sect.uDEnd = m_vSections [iSection].uDEnd;
00271 LeaveCriticalSection (&m_csSections);
00272
00273 ASSERT (sect.uStart != 0);
00274
00275 TSECT(§);
00276
00277 ir = OpenUrl (sect.uStart, §.file, -1, sect.nMirrorURL, m_uSSFileSize != _UI64_MAX);
00278
00279 if (IsDone () == TRUE)
00280 {
00281 SAFE_DELETE (sect.file);
00282 if (nMirrorInc == UINT_MAX)
00283 m_cBaseSectCreatingNow--;
00284 else
00285 m_vMirrs [nMirrorInc].cSectsCreatingNow --;
00286
00287 m_bAddingSection = FALSE;
00288 LeaveCriticalSection (&m_csAddSection);
00289 return IR_S_FALSE;
00290 }
00291
00292 if (ir != IR_SUCCESS)
00293 {
00294 if (nMirrorInc == UINT_MAX)
00295 m_cBaseSectCreatingNow--;
00296 else
00297 m_vMirrs [nMirrorInc].cSectsCreatingNow --;
00298
00299 m_bAddingSection = FALSE;
00300 LeaveCriticalSection (&m_csAddSection);
00301 return ir;
00302 }
00303
00304 EnterCriticalSection (&m_csSections);
00305 m_vSections [iSection].uEnd = sect.uStart;
00306 m_vSections [iSection].uDEnd = sect.uDStart;
00307 LeaveCriticalSection (&m_csSections);
00308
00309 if (sect.nMirrorURL != nMirrorInc)
00310 {
00311 if (nMirrorInc == UINT_MAX)
00312 m_cBaseSectCreatingNow--;
00313 else
00314 m_vMirrs [nMirrorInc].cSectsCreatingNow --;
00315
00316 if (sect.nMirrorURL == UINT_MAX)
00317 m_cBaseSectCreatingNow++;
00318 else
00319 m_vMirrs [sect.nMirrorURL].cSectsCreatingNow++;
00320 }
00321
00322 CreateSection (sect);
00323
00324 EnterCriticalSection (&m_csSections);
00325 if (m_vSections [iSection].uEnd < m_vSections [iSection].uCurrent)
00326 {
00327 m_vSections [iSection].uEnd = m_vSections [iSection].uCurrent;
00328 m_vSections [iSection].uDEnd = m_vSections [iSection].uDCurrent;
00329 }
00330 LeaveCriticalSection (&m_csSections);
00331
00332 m_bAddingSection = FALSE;
00333 LeaveCriticalSection (&m_csAddSection);
00334
00335 return IR_SUCCESS;
00336 }
00337
00338 BOOL fsInternetDownloader::CreateSection(fsSection §, BOOL bCreateThread, BOOL bReduceSCN)
00339 {
00340 sect.uSpeed = 0;
00341 sect.pThis = this;
00342 sect.lastErr = IR_SUCCESS;
00343 sect.uSpeedLimit = 0;
00344 sect.state = bCreateThread ? SS_CREATING : SS_STOPPED;
00345 sect.iSection = m_vSections.size ();
00346
00347 if (sect.iSection == 0 && bCreateThread)
00348 {
00349
00350 if (FALSE == Event (DE_NEEDFILE))
00351 return FALSE;
00352 }
00353
00354 m_vSections.add (sect);
00355 fsSection* pSect = &m_vSections [m_vSections.size ()-1];
00356
00357 if (sect.iSection == 0 && bCreateThread)
00358 {
00359 if (FALSE == Event (DE_NEEDFILE_FINALINITIALIZATION))
00360 return FALSE;
00361 }
00362
00363 if (bCreateThread)
00364 {
00365 Event (DE_SECTIONADDED, sect.iSection);
00366 DWORD dwThread;
00367 if (bReduceSCN)
00368 {
00369 if (sect.nMirrorURL == UINT_MAX)
00370 m_cBaseSectCreatingNow--;
00371 else
00372 m_vMirrs [sect.nMirrorURL].cSectsCreatingNow--;
00373 }
00374 m_cThreads++; m_cRunningThreads++;
00375 Event (DE_SECTIONSTARTED, sect.iSection);
00376 CloseHandle (CreateThread (NULL, 0, _threadDownload, pSect, 0, &dwThread));
00377 }
00378
00379 return TRUE;
00380 }
00381
00382 BOOL fsInternetDownloader::__threadDownload_flushdata (fsSectionEx* sect,
00383 LPBYTE pBuffer, DWORD dwRead,
00384 LPBYTE &pbCache, DWORD &dwCacheSize, DWORD &dwCacheLen)
00385 {
00386 if (pBuffer == NULL && pbCache == NULL)
00387 return TRUE;
00388
00389 if (pBuffer && pbCache)
00390 {
00391 DWORD dwNewCacheSize = sect->pThis->m_dwForceCacheSizePerSection != DWORD (-1) ?
00392 sect->pThis->m_dwForceCacheSizePerSection :
00393 #ifndef FDM_DLDR__RAWCODEONLY
00394 _App.FileWriteCacheSize () / sect->pThis->GetRunningSectionCount ();
00395 #else
00396 0;
00397 #endif
00398
00399 if (dwNewCacheSize < dwCacheSize)
00400 {
00401
00402 if (FALSE == __threadDownload_flushdata (sect, NULL, 0, pbCache, dwCacheSize, dwCacheLen))
00403 return FALSE;
00404 return __threadDownload_flushdata (sect, pBuffer, dwRead, pbCache, dwCacheSize, dwCacheLen);
00405 }
00406 }
00407
00408 __int64 iLenCorrection;
00409
00410 DWORD dwWrittenTotal = 0;
00411
00412 if (pBuffer == NULL || dwCacheSize - dwCacheLen < dwRead)
00413 {
00414 EnterCriticalSection (§->pThis->m_csWriteToFile);
00415
00416 fsSetFilePointer (sect->pThis->m_hOutFile, sect->uDCurrent, FILE_BEGIN);
00417
00418 BOOL bWriteOk = TRUE;
00419 DWORD dwWrite = 0;
00420
00421 if (dwCacheLen)
00422 {
00423 bWriteOk = WriteFile (sect->pThis->m_hOutFile, pbCache, dwCacheLen, &dwWrite, NULL);
00424 bWriteOk = bWriteOk && (dwCacheLen == dwWrite);
00425 }
00426
00427 if (bWriteOk && dwRead)
00428 {
00429 bWriteOk = WriteFile (sect->pThis->m_hOutFile, pBuffer, dwRead, &dwWrite, NULL);
00430 bWriteOk = bWriteOk && (dwRead == dwWrite);
00431 }
00432
00433 LeaveCriticalSection (§->pThis->m_csWriteToFile);
00434
00435 if (!bWriteOk)
00436 return FALSE;
00437
00438 dwWrittenTotal = dwCacheLen + dwRead;
00439
00440 #ifndef FDM_DLDR__RAWCODEONLY
00441
00442 DWORD dwNewCacheSize = sect->pThis->m_dwForceCacheSizePerSection != DWORD (-1) ?
00443 sect->pThis->m_dwForceCacheSizePerSection :
00444 _App.FileWriteCacheSize () / sect->pThis->GetRunningSectionCount ();
00445
00446 iLenCorrection = - (__int64)dwCacheLen;
00447 dwCacheLen = 0;
00448
00449 if (dwCacheSize != dwNewCacheSize)
00450 {
00451
00452 SAFE_DELETE_ARRAY (pbCache);
00453 dwCacheSize = 0;
00454 }
00455
00456 if (pbCache == NULL && dwNewCacheSize)
00457 {
00458 try {
00459 pbCache = new BYTE [dwNewCacheSize];
00460 if (pbCache)
00461 dwCacheSize = dwNewCacheSize;
00462 }catch (...) {}
00463 }
00464 #endif
00465
00466 }
00467 else
00468 {
00469 CopyMemory (pbCache + dwCacheLen, pBuffer, dwRead);
00470 dwCacheLen += dwRead;
00471 iLenCorrection = dwRead;
00472 }
00473
00474 EnterCriticalSection (§->pThis->m_csSections);
00475
00476 __int64 i = sect->pThis->m_dwDataLenInCache;
00477 i += iLenCorrection;
00478
00479 sect->pThis->m_dwDataLenInCache = (DWORD)i;
00480
00481 if (dwWrittenTotal)
00482 {
00483 sect->uCurrent += dwWrittenTotal;
00484 sect->uDCurrent += dwWrittenTotal;
00485 }
00486
00487 LeaveCriticalSection (§->pThis->m_csSections);
00488
00489 return TRUE;
00490 }
00491
00492 DWORD WINAPI fsInternetDownloader::_threadDownload(LPVOID lp)
00493 {
00494
00495 #define CHECK_NEED_STOP if (sect->pThis->m_bNeedStop || sect->state == SS_NEEDSTOP) { sect->state = SS_STOPPED; goto _exit; }
00496
00497 const int BufDivider = 8;
00498
00499 fsSectionEx *sect = (fsSectionEx*) lp;
00500 fsDownload_NetworkProperties *dnp = sect->pThis->DNP (sect->iSection);
00501
00502 TSECT (sect);
00503
00504 LOG ("fsID::_thrDL [" << sect->iSection << "] enter in..." << nl);
00505 LOG ("fsID::_thrDL [" << sect->iSection << "] section info" << nl);
00506 LOG ("fsID::_thrDL [" << sect->iSection << "] start = " << sect->uStart << nl);
00507 LOG ("fsID::_thrDL [" << sect->iSection << "] current = " << sect->uCurrent << nl);
00508 LOG ("fsID::_thrDL [" << sect->iSection << "] end = " << sect->uEnd << nl);
00509
00510 DWORD dwBufSize = 2000;
00511 BYTE *pBuffer = new BYTE [dwBufSize];
00512 ZeroMemory (pBuffer, dwBufSize);
00513 DWORD dwMaxRead = is_PauseMode () ? 1 : dwBufSize;
00514 DWORD dwRead;
00515 DWORD dwLastRead = 0;
00516 fsTicksMgr timeOld, timeNew;
00517
00518 LPBYTE pbCache = NULL;
00519 DWORD dwCacheSize = 0;
00520 sect->dwCacheLen = 0;
00521
00522 vmsSpeedTracker st;
00523 if (sect->pThis->m_dnp.dwFlags & DNPF_RESTARTSECTIONWHENSPEEDTOOLOW)
00524 {
00525 st.set_LowSpeedDuration (sect->pThis->m_dnp.wLowSpeed_Duration * 60);
00526 st.set_LowSpeedFactor (sect->pThis->m_dnp.wLowSpeed_Factor);
00527 }
00528 else
00529 st.set_LowSpeedDuration (INT_MAX);
00530
00531 LOG ("fsID::_thrDL [" << sect->iSection << "] buf size is 1000" << nl);
00532
00533 timeOld.Now ();
00534 timeNew.Now ();
00535
00536 int cZeroReads;
00537 cZeroReads = 0;
00538 fsTicksMgr tickZRStart;
00539
00540 CHECK_NEED_STOP;
00541
00542 if (sect->file)
00543 {
00544 LOG ("fsID::_thrDL [" << sect->iSection << "] prepairing dl..." << nl);
00545
00546 sect->file->SetDialogFunc (_InetFileDialogFunc, sect->pThis, LPVOID (sect->iSection));
00547 sect->state = SS_DOWNLOADING;
00548 sect->pThis->Event (DE_SECTDOWNLOADING, sect->iSection);
00549
00550 LOG ("fsID::_thrDL [" << sect->iSection << "] r 0-size" << nl);
00551
00552 sect->file->Read (pBuffer, 0, &dwRead);
00553 }
00554
00555 sect->pThis->UpdateTrafficLimit ();
00556
00557 BOOL bMayZIP;
00558 bMayZIP = sect->uStart == 0 && sect->uCurrent < ZIP_SFXMAXSIZE &&
00559 sect->pThis->IsMayZIP (TRUE) && sect->pThis->m_vSections.size () == 1;
00560 UINT32 uLast3BytesRead;
00561 uLast3BytesRead = 0;
00562
00563 #ifdef _USELOGGING
00564 if (bMayZIP)
00565 LOG ("fsID::_thrDL [" << sect->iSection << "] probably is ZIP" << nl);
00566 #endif
00567
00568 #define CURRENT_DL_POS (sect->uCurrent + sect->dwCacheLen)
00569
00570 #define CURRENT_DW_POS (sect->uDCurrent + sect->dwCacheLen)
00571
00572 while (sect->uEnd > CURRENT_DL_POS)
00573 {
00574 CHECK_NEED_STOP;
00575
00576 dwRead = dwMaxRead;
00577 if (dwRead >= sect->uEnd - CURRENT_DL_POS)
00578 {
00579 dwRead = DWORD (sect->uEnd - CURRENT_DL_POS);
00580
00581 EnterCriticalSection (§->pThis->m_csSections);
00582 if (dnp->enProtocol == NP_FTP && sect->file->FtpGetTransferType () == FTT_ASCII && sect->uEnd == sect->file->GetFileSize ())
00583 sect->uEnd += 100;
00584 LeaveCriticalSection (§->pThis->m_csSections);
00585 }
00586
00587 if (sect->uEnd - CURRENT_DL_POS - dwRead < 100)
00588 {
00589 dwRead += (DWORD)(sect->uEnd - CURRENT_DL_POS - dwRead);
00590 if (dwRead > dwMaxRead)
00591 {
00592
00593 delete [] pBuffer;
00594 dwMaxRead = dwRead;
00595 pBuffer = new BYTE [dwMaxRead];
00596 }
00597 }
00598
00599 ASSERT (dwRead <= dwMaxRead);
00600
00601 if (sect->file)
00602 {
00603
00604 sect->lastErr = sect->file->Read (pBuffer, dwRead, &dwRead);
00605 }
00606 else
00607 {
00608 LOG ("fsID::_thrDL [" << sect->iSection << "] read error " << sect->lastErr << nl);
00609
00610
00611 if (sect->lastErr == IR_SUCCESS || sect->lastErr == IR_S_FALSE)
00612 sect->lastErr = IR_ERROR;
00613 }
00614
00615 if (dwRead == 0 && sect->lastErr == IR_SUCCESS)
00616 {
00617 LOG ("fsID::_thrDL [" << sect->iSection << "] 0 read. count is " << cZeroReads << nl);
00618 LOG ("fsID::_thrDL [" << sect->iSection << "] to read is " << dwRead << nl);
00619
00620 if (cZeroReads == 0)
00621 tickZRStart.Now ();
00622 else
00623 {
00624 fsTicksMgr tickNow; tickNow.Now ();
00625
00626 if (tickNow - tickZRStart > 60*1000)
00627 {
00628
00629 LOG ("fsID::_thrDL [" << sect->iSection << "] 0 read (2)" << nl);
00630
00631 {
00632 fsInternetURLFile *file = sect->file;
00633 sect->file = NULL;
00634 delete file;
00635 sect->lastErr = IR_WININETUNKERROR;
00636 sect->state = SS_ERRSTOPPED;
00637 goto _exit;
00638 }
00639
00640 LOG ("fsID::_thrDL [" << sect->iSection << "] 0 read (4)" << nl);
00641 cZeroReads = 101;
00642 }
00643 }
00644
00645 if (cZeroReads++ > 100)
00646 {
00647 if (sect->uEnd == _UI64_MAX ||
00648 (sect->uEnd >= sect->file->GetFileSize () && sect->file->FtpGetTransferType () == FTT_ASCII && dnp->enProtocol == NP_FTP))
00649 {
00650 EnterCriticalSection (§->pThis->m_csSections);
00651 sect->uEnd = CURRENT_DL_POS;
00652 sect->uDEnd = sect->pThis->m_uLDFileSize = CURRENT_DW_POS;
00653 LeaveCriticalSection (§->pThis->m_csSections);
00654 TSECT (sect);
00655 break;
00656 }
00657 else
00658 {
00659 LOG ("fsID::_thrDL [" << sect->iSection << "] 0 read (5)" << nl);
00660 sect->lastErr = IR_LOSTCONNECTION;
00661 }
00662 }
00663 else
00664 {
00665 Sleep (5);
00666 continue;
00667 }
00668 }
00669 cZeroReads = 0;
00670
00671 if (sect->lastErr != IR_SUCCESS)
00672 {
00673 sect->pThis->m_speed.Reset ();
00674 sect->uSpeed = 0;
00675 st.Reset ();
00676
00677 if (sect->file)
00678 {
00679 LOG ("fsID::_thrDL [" << sect->iSection << "] performing rollback" << nl);
00680
00681 DWORD dw = sect->pThis->DNP (sect->iSection)->wRollBackSize;
00682 DWORD dw2 = (WORD)(CURRENT_DL_POS - sect->uStart);
00683 DWORD dw3 = (WORD)(CURRENT_DW_POS - sect->uDStart);
00684
00685 dw = min (dw, dw2); dw = min (dw, dw3);
00686 EnterCriticalSection (§->pThis->m_csSections);
00687
00688 if (sect->dwCacheLen)
00689 {
00690 if (sect->dwCacheLen >= dw)
00691 {
00692 sect->dwCacheLen -= dw;
00693 dw = 0;
00694 }
00695 else
00696 {
00697 dw -= sect->dwCacheLen;
00698 sect->dwCacheLen = 0;
00699 }
00700 }
00701
00702 sect->uCurrent -= dw;
00703 sect->uDCurrent -= dw;
00704
00705 LeaveCriticalSection (§->pThis->m_csSections);
00706 TSECT (sect);
00707 }
00708
00709 CHECK_NEED_STOP;
00710 sect->state = SS_ERROR;
00711 if (sect->file)
00712 sect->pThis->Event (DE_ERROROCCURED, sect->iSection);
00713
00714 LOG ("fsID::_thrDL [" << sect->iSection << "] del file" << nl);
00715
00716 SAFE_DELETE (sect->file);
00717
00718 sect->pThis->UpdateTrafficLimit ();
00719
00720 while (sect->pThis->m_bErrDownloading)
00721 {
00722 Sleep (100);
00723 CHECK_NEED_STOP;
00724 }
00725
00726 CHECK_NEED_STOP;
00727 sect->state = SS_RECONNECTING;
00728
00729 sect->pThis->m_bErrDownloading = TRUE;
00730
00731 UINT cAttempts = sect->pThis->m_uMaxAttempts;
00732
00733 LOG ("fsID::_thrDL [" << sect->iSection << "] reconnecting..." << nl);
00734
00735 do
00736 {
00737 if (cAttempts == 0 || sect->pThis->m_bNeedStop || sect->state == SS_NEEDSTOP)
00738 {
00739 if (sect->pThis->m_bNeedStop || sect->state == SS_NEEDSTOP)
00740 sect->state = SS_STOPPED;
00741 else
00742 sect->state = SS_ERRSTOPPED;
00743
00744 sect->pThis->m_bErrDownloading = FALSE;
00745
00746 LOG ("fsID::_thrDL [" << sect->iSection << "] failed to reconnect" << nl);
00747
00748 goto _exit;
00749 }
00750
00751 sect->pThis->Event (DE_CONNECTING, sect->iSection);
00752 sect->lastErr = sect->pThis->OpenUrl (CURRENT_DL_POS, §->file, sect->iSection, sect->nMirrorURL, TRUE);
00753
00754 if (sect->lastErr != IR_SUCCESS)
00755 {
00756 sect->pThis->Event (DE_FAILCONNECT, sect->iSection);
00757
00758 if (sect->lastErr == IR_RANGESNOTAVAIL || sect->lastErr == IR_DOUBTFUL_RANGESRESPONSE)
00759 {
00760 sect->state = SS_ERRSTOPPED;
00761 sect->pThis->m_bErrDownloading = FALSE;
00762
00763 LOG ("fsID::_thrDL [" << sect->iSection << "] failed to reconnect (2)" << nl);
00764
00765 goto _exit;
00766 }
00767
00768 cAttempts--;
00769
00770 if (cAttempts && sect->pThis->m_uRetryTime)
00771 {
00772 sect->pThis->Event (DE_PAUSE, sect->iSection);
00773 sect->pThis->SleepInterval ();
00774 }
00775 }
00776
00777 } while (sect->lastErr != IR_SUCCESS);
00778
00779 LOG ("fsID::_thrDL [" << sect->iSection << "] connected ok." << nl);
00780
00781 sect->pThis->m_bErrDownloading = FALSE;
00782 CHECK_NEED_STOP;
00783 sect->state = SS_DOWNLOADING;
00784 sect->pThis->Event (DE_CONNECTED, sect->iSection);
00785 sect->pThis->Event (DE_SECTDOWNLOADING, sect->iSection);
00786
00787 sect->pThis->UpdateTrafficLimit ();
00788
00789 timeNew.Now ();
00790 timeOld.Now ();
00791 dwLastRead = 0;
00792
00793 continue;
00794 }
00795
00796 BOOL bWriteOk = __threadDownload_flushdata (sect, pBuffer, dwRead, pbCache,
00797 dwCacheSize, sect->dwCacheLen);
00798
00799 if (!bWriteOk)
00800 {
00801 CHECK_NEED_STOP;
00802 sect->state = SS_WRITEERROR;
00803 sect->lastErr = (fsInternetResult) GetLastError ();
00804 goto _exit;
00805 }
00806
00807 TSECT (sect);
00808 dwLastRead += dwRead;
00809 sect->pThis->m_speed.Done (dwRead);
00810 fsInternetDownloader::OnDataDownloaded (dwRead);
00811
00812 if (bMayZIP)
00813 {
00814 LPBYTE pBuf = pBuffer;
00815 BOOL bZIP = FALSE;
00816
00817 UINT64 uZIPStart = 0;
00818
00819 for (int i = 0; i <= (int)dwRead - (int)sizeof (UINT32); i++)
00820 {
00821 UINT32* p = (UINT32*)(pBuf++);
00822 if (*p == ZIP_BEGIN_SIG)
00823 {
00824 bZIP = TRUE;
00825 uZIPStart = CURRENT_DL_POS - dwRead + i;
00826 break;
00827 }
00828 }
00829
00830 if (bZIP == FALSE && uLast3BytesRead)
00831 {
00832 BYTE buf [3+3];
00833
00834 buf [0] = BYTE (uLast3BytesRead);
00835 buf [1] = BYTE (uLast3BytesRead >> 8);
00836 buf [2] = BYTE (uLast3BytesRead >> 16);
00837 buf [3] = pBuffer [0];
00838 buf [4] = pBuffer [1];
00839 buf [5] = pBuffer [2];
00840
00841 for (UINT i = 0; i <= 6-sizeof(UINT32); i++)
00842 {
00843 UINT32* p = (UINT32*)(buf+i);
00844 if (*p == ZIP_BEGIN_SIG)
00845 {
00846 LOG ("fsID::_thrDL [" << sect->iSection << "] ZIP detected" << nl);
00847 bZIP = TRUE;
00848 uZIPStart = CURRENT_DL_POS - dwRead - i + 3;
00849 break;
00850 }
00851 }
00852 }
00853
00854 uLast3BytesRead = UINT32 (pBuffer [dwRead-1]) << 16 |
00855 UINT32 (pBuffer [dwRead-2]) << 8 | UINT32 (pBuffer [dwRead-3]);
00856
00857 if (bZIP)
00858 {
00859 fsInternetDownloader* pThis = sect->pThis;
00860
00861 pThis->m_speed.Reset ();
00862
00863 fsInternetResult ir = sect->pThis->CheckIsZIP (uZIPStart, §->file);
00864
00865 if (IR_SUCCESS == ir)
00866 {
00867 SAFE_DELETE_ARRAY (pBuffer);
00868 pThis->m_cRunningThreads--;
00869 pThis->Event (DE_SECTIONSTOPPED, 0);
00870 pThis->m_cThreads--;
00871 return 0;
00872 }
00873 else
00874 {
00875 if (ir == 0x1000)
00876 {
00877 sect->pThis->m_bNeedStop = TRUE;
00878 EnterCriticalSection (§->pThis->m_csSections);
00879
00880 sect->uDCurrent -= CURRENT_DL_POS - uZIPStart;
00881 sect->uCurrent = uZIPStart;
00882 sect->dwCacheLen -= min (sect->dwCacheLen, (DWORD)(CURRENT_DL_POS - uZIPStart));
00883 LeaveCriticalSection (§->pThis->m_csSections);
00884 TSECT (sect);
00885 CHECK_NEED_STOP;
00886 }
00887 else if (ir == IR_S_FALSE && sect->pThis->m_bNeedStop == FALSE)
00888 {
00889 bMayZIP = FALSE;
00890 sect->pThis->Event (DE_MAYADDSECTION);
00891 }
00892 else
00893 {
00894 sect->state = SS_ERRSTOPPED;
00895 EnterCriticalSection (§->pThis->m_csSections);
00896 sect->uDCurrent -= CURRENT_DL_POS - uZIPStart;
00897 sect->uCurrent = uZIPStart;
00898 sect->dwCacheLen -= min (sect->dwCacheLen, (DWORD)(CURRENT_DL_POS - uZIPStart));
00899 LeaveCriticalSection (§->pThis->m_csSections);
00900 TSECT (sect);
00901 goto _exit;
00902 }
00903 }
00904 }
00905
00906 if (CURRENT_DL_POS > ZIP_SFXMAXSIZE)
00907 {
00908 bMayZIP = FALSE;
00909 sect->pThis->Event (DE_MAYADDSECTION);
00910 }
00911 }
00912
00913 timeNew.Now ();
00914
00915 UINT uSpeedLimit = is_PauseMode () ? 1 : sect->uSpeedLimit;
00916 if (timeNew - timeOld >= 1000 || dwLastRead >= uSpeedLimit)
00917 {
00918 if (timeNew - timeOld >= 1000)
00919 {
00920
00921 sect->uSpeed = (UINT)((dwLastRead) / ((double)(timeNew - timeOld) / 1000.0f));
00922
00923 st.CurrentSpeedIs (sect->uSpeed);
00924 if (st.CheckCurrentSpeedTooLow ())
00925 {
00926 sect->pThis->Event (DE_SPEEDISTOOLOW, sect->iSection);
00927 SAFE_DELETE (sect->file);
00928 }
00929 }
00930 else
00931 {
00932 sect->uSpeed = dwLastRead;
00933 st.Reset ();
00934 }
00935
00936 dwLastRead = 0;
00937
00938 if (timeNew - timeOld < 1000)
00939 {
00940 dwMaxRead = uSpeedLimit / BufDivider;
00941
00942 Sleep (1000 - (timeNew - timeOld));
00943 }
00944 else
00945 {
00946 dwMaxRead = sect->uSpeed / BufDivider;
00947 }
00948
00949 if (dwMaxRead > 100000)
00950 dwMaxRead = 100000;
00951 else if (dwMaxRead == 0)
00952 dwMaxRead = 1;
00953
00954 if (dwBufSize < dwMaxRead)
00955 {
00956
00957 LOG ("fsID::_thrDL [" << sect->iSection << "] buf size is " << dwMaxRead << nl);
00958 delete [] pBuffer;
00959 pBuffer = new BYTE [dwMaxRead];
00960 dwBufSize = dwMaxRead;
00961 }
00962
00963 timeOld.Now ();
00964 }
00965 }
00966
00967 if (pbCache && sect->dwCacheLen)
00968 {
00969
00970 BOOL bWriteOk = __threadDownload_flushdata (sect, NULL, 0, pbCache, dwCacheSize, sect->dwCacheLen);
00971 if (!bWriteOk)
00972 {
00973 CHECK_NEED_STOP;
00974 sect->state = SS_WRITEERROR;
00975 sect->lastErr = (fsInternetResult) GetLastError ();
00976 goto _exit;
00977 }
00978 }
00979
00980 EnterCriticalSection (§->pThis->m_csSections);
00981 sect->uCurrent = sect->uEnd;
00982 if (sect->uDCurrent > sect->uDEnd)
00983 sect->uDCurrent = sect->uDEnd;
00984 LeaveCriticalSection (§->pThis->m_csSections);
00985 TSECT (sect);
00986 sect->state = SS_DONE;
00987
00988 _exit:
00989 LOG ("fsID::_thrDL [" << sect->iSection << "] del file (2)" << nl);
00990 fsInternetURLFile *file = sect->file;
00991 sect->file = NULL;
00992 delete file;
00993 SAFE_DELETE_ARRAY (pBuffer);
00994
00995 if (pbCache && sect->dwCacheLen)
00996 __threadDownload_flushdata (sect, NULL, 0, pbCache, dwCacheSize, sect->dwCacheLen);
00997 if (sect->dwCacheLen)
00998 {
00999 EnterCriticalSection (§->pThis->m_csSections);
01000 sect->pThis->m_dwDataLenInCache -= sect->dwCacheLen;
01001 LeaveCriticalSection (§->pThis->m_csSections);
01002 }
01003 SAFE_DELETE_ARRAY (pbCache);
01004
01005 EnterCriticalSection (§->pThis->m_csDone);
01006
01007 sect->pThis->m_cRunningThreads--;
01008
01009 switch (sect->state)
01010 {
01011 case SS_DONE:
01012 if (sect->nMirrorURL != UINT_MAX)
01013 sect->pThis->m_vMirrs [sect->nMirrorURL].bIsGood = TRUE;
01014 EnterCriticalSection (§->pThis->m_csSections);
01015 if (sect->uDEnd == _UI64_MAX || sect->uEnd == _UI64_MAX)
01016 {
01017 sect->uEnd = sect->uCurrent;
01018 sect->uDEnd = sect->uDCurrent;
01019 }
01020 LeaveCriticalSection (§->pThis->m_csSections);
01021 sect->pThis->Event (DE_SECTIONDONE, sect->iSection);
01022 break;
01023
01024 case SS_WRITEERROR:
01025 sect->pThis->Event (DE_WRITEERROR, sect->iSection);
01026 case SS_STOPPED:
01027 case SS_ERRSTOPPED:
01028 sect->pThis->Event (DE_SECTIONSTOPPED, sect->iSection);
01029 sect->state = SS_STOPPED;
01030 break;
01031 }
01032
01033 if (sect->pThis->m_cRunningThreads == 0)
01034 {
01035 sect->pThis->m_speed.Reset ();
01036 sect->pThis->m_dwDataLenInCache = 0;
01037 sect->pThis->Event (DE_ALLSTOPPEDORDONE);
01038 }
01039
01040 sect->pThis->UpdateTrafficLimit ();
01041
01042 sect->pThis->m_cThreads--;
01043
01044 LeaveCriticalSection (§->pThis->m_csDone);
01045
01046 LOG ("fsID::_thrDL [" << sect->iSection << "] exit." << nl);
01047
01048 return 0;
01049 }
01050
01051 fsInternetResult fsInternetDownloader::OpenUrl(UINT64 uStartPos, fsInternetURLFile **ppFile, int iSectIndex, UINT &nMirror, BOOL bCheckFileSize, LPCSTR pszContentTypeReq)
01052 {
01053 return OpenUrl_imp (uStartPos, ppFile, iSectIndex, nMirror, bCheckFileSize, 0, pszContentTypeReq);
01054 }
01055
01056 fsInternetResult fsInternetDownloader::OpenUrl_imp(UINT64 uStartPos, fsInternetURLFile **ppFile, int iSectIndex, UINT &nMirror, BOOL bCheckFileSize, int iAttempt, LPCSTR )
01057 {
01058 fsInternetResult ir;
01059 fsDownload_NetworkProperties* dnp;
01060
01061 LOG ("fsID::OU_i: opening url..." << nl);
01062 LOG ("fsID::OU_i: mirror: " << (DWORD)nMirror << nl);
01063
01064 *ppFile = NULL;
01065
01066 if (iAttempt > 15)
01067 return IR_ERROR;
01068
01069 EnterCriticalSection (&m_csOpenUrl);
01070 if (m_bNeedStop)
01071 {
01072 LeaveCriticalSection (&m_csOpenUrl);
01073 return IR_S_FALSE;
01074 }
01075
01076 dnp = nMirror == UINT_MAX ? DNP (iSectIndex) : &m_vMirrs [nMirror].dnp;
01077
01078 ASSERT (m_pOpeningFile == NULL);
01079 fsnew1 (m_pOpeningFile, fsInternetURLFile);
01080 m_pOpeningFile->SetDialogFunc (_InetFileDialogFunc, this, LPVOID (iSectIndex));
01081
01082 vmsInternetSession* pSession = new vmsInternetSession;
01083 char szProxy [10000];
01084 vmsMakeWinInetProxy (dnp->pszProxyName, dnp->enProtocol, dnp->enProtocol, szProxy);
01085 ir = pSession->Create (dnp->pszAgent, dnp->enAccType, szProxy, dnp->enProtocol);
01086 if (ir != IR_SUCCESS)
01087 {
01088 LOG ("fsID::OU_i: openurl failed" << nl);
01089 delete pSession;
01090 SAFE_DELETE (m_pOpeningFile);
01091 LeaveCriticalSection (&m_csOpenUrl);
01092 return ir;
01093 }
01094
01095 ApplyProxySettings (pSession, dnp);
01096
01097 m_pOpeningFile->Initialize (pSession, TRUE);
01098
01099 ApplyProperties (m_pOpeningFile, dnp);
01100
01101 if (dnp->enProtocol == NP_FTP && dnp->enFtpTransferType == FTT_UNKNOWN)
01102 {
01103 int posPath = strlen (dnp->pszPathName) - 1;
01104 int posExt = 0;
01105 LPSTR pszExt = new char [MY_MAX_PATH];
01106
01107 while (posPath && dnp->pszPathName [posPath] != '.')
01108 pszExt [posExt++] = dnp->pszPathName [posPath--];
01109
01110 if (posPath)
01111 {
01112 LPSTR pszExtension = new char [MY_MAX_PATH];
01113
01114 pszExt [posExt] = 0;
01115
01116 for (int i = 0; i < posExt; i++)
01117 pszExtension [i] = pszExt [posExt - i - 1];
01118
01119 pszExtension [i] = 0;
01120
01121 if (IsExtInExtsStr (dnp->pszASCIIExts, pszExtension))
01122 m_pOpeningFile->FtpSetTransferType (FTT_ASCII);
01123 else
01124 m_pOpeningFile->FtpSetTransferType (FTT_BINARY);
01125
01126 delete [] pszExtension;
01127 }
01128 else
01129 {
01130 m_pOpeningFile->FtpSetTransferType (FTT_BINARY);
01131 }
01132
01133 delete [] pszExt;
01134 }
01135
01136 LOG ("fsID::OU_i(" << (DWORD)this << "): opening url (" << (DWORD)m_pOpeningFile << ")" << nl);
01137
01138 _inc_tOU_param *p = new _inc_tOU_param;
01139 p->pthis = this;
01140 p->uStartPos = uStartPos;
01141 p->pFile =m_pOpeningFile;
01142 p->dnp = dnp;
01143 DWORD dw;
01144 HANDLE hOpen = CreateThread (NULL, 0, _threadOpenUrl, p, 0, &dw);
01145 while (WAIT_TIMEOUT == WaitForSingleObject (hOpen, 333))
01146 {
01147 if (m_bNeedStop)
01148 TerminateThread (hOpen, IR_S_FALSE);
01149 }
01150 GetExitCodeThread (hOpen, &dw);
01151 CloseHandle (hOpen);
01152
01153 ir = (fsInternetResult)dw;
01154
01155 LOG ("fsID::OU_i(" << (DWORD)this << "): opened ok." << nl);
01156
01157 if (m_bNeedStop)
01158 {
01159 LOG ("fsID::OU_i: openurl failed" << nl);
01160 SAFE_DELETE (m_pOpeningFile);
01161 LeaveCriticalSection (&m_csOpenUrl);
01162 return IR_S_FALSE;
01163 }
01164
01165 if (ir == IR_SUCCESS && bCheckFileSize && m_uSSFileSize != _UI64_MAX)
01166 {
01167 if (m_pOpeningFile->GetFileSize () != m_uSSFileSize)
01168 ir = IR_BADFILESIZE;
01169 }
01170
01171 if (ir != IR_SUCCESS)
01172 {
01173 if (ir == IR_NEEDREDIRECT)
01174 {
01175 if (m_vSections.size ())
01176 {
01177 SAFE_DELETE (m_pOpeningFile);
01178 LeaveCriticalSection (&m_csOpenUrl);
01179 LOG ("fsID::OU_i: openurl failed" << nl);
01180 return IR_SERVERUNKERROR;
01181 }
01182
01183 LPCSTR pszUrlTo = m_pOpeningFile->GetLastError ();
01184
01185 fsURL url;
01186 LPSTR pszUrl = new char [10000];
01187 DWORD dwLen = 10000;
01188
01189 LOG ("fsID::OU_i: Redirecting to: " << pszUrlTo << nl);
01190
01191 if (url.Crack (pszUrlTo) != IR_SUCCESS)
01192 {
01193 LPSTR pszUrlPath = new char [10000];
01194
01195 if (*pszUrlTo == 0)
01196 strcpy (pszUrlPath, "/");
01197 else if (*pszUrlTo != '/' && *pszUrlTo != '\\')
01198 {
01199
01200 fsPathFromUrlPath (dnp->pszPathName, dnp->enProtocol == NP_FTP, FALSE, pszUrlPath, 10000);
01201
01202 if (pszUrlPath [lstrlen (pszUrlPath)-1] != '\\' &&
01203 pszUrlPath [lstrlen (pszUrlPath)-1] != '/')
01204 lstrcat (pszUrlPath, "\\");
01205
01206 strcat (pszUrlPath, pszUrlTo);
01207 }
01208 else
01209 strcpy (pszUrlPath, pszUrlTo);
01210
01211
01212 url.Create (fsNPToScheme (dnp->enProtocol), dnp->pszServerName, dnp->uServerPort,
01213 dnp->pszUserName, dnp->pszPassword, pszUrlPath, pszUrl, &dwLen);
01214
01215 delete [] pszUrlPath;
01216 }
01217 else
01218 strcpy (pszUrl, pszUrlTo);
01219
01220 Event (DE_REDIRECTING);
01221
01222
01223 LPSTR pszUser = new char [10000], pszPassword = new char [10000];
01224 if (dnp->pszUserName)
01225 strcpy (pszUser, dnp->pszUserName);
01226 else
01227 *pszUser = 0;
01228
01229 if (dnp->pszPassword)
01230 strcpy (pszPassword, dnp->pszPassword);
01231 else
01232 *pszPassword = 0;
01233
01234
01235 ir = fsDNP_ApplyUrl (dnp, pszUrl);
01236
01237 delete [] pszUrl;
01238
01239 if (ir != IR_SUCCESS)
01240 {
01241
01242 SAFE_DELETE (m_pOpeningFile);
01243 LeaveCriticalSection (&m_csOpenUrl);
01244 LOG ("fsID::OU_i: openurl failed" << nl);
01245 return ir;
01246 }
01247
01248 if (dnp->pszUserName == NULL || *dnp->pszUserName == 0)
01249 {
01250 SAFE_DELETE_ARRAY (dnp->pszUserName);
01251 dnp->pszUserName = new char [strlen (pszUser) + 1];
01252 strcpy (dnp->pszUserName, pszUser);
01253
01254 SAFE_DELETE_ARRAY (dnp->pszPassword);
01255 dnp->pszPassword = new char [strlen (pszPassword) + 1];
01256 strcpy (dnp->pszPassword, pszPassword);
01257 }
01258
01259 delete [] pszUser; delete [] pszPassword;
01260
01261 Event (DE_REDIRECTINGOKCONTINUEOPENING);
01262
01263 SAFE_DELETE (m_pOpeningFile);
01264 LeaveCriticalSection (&m_csOpenUrl);
01265 LOG ("fsID::OU_i: calling openurl again..." << nl);
01266 if (m_bNeedStop == FALSE)
01267 return OpenUrl_imp (uStartPos, ppFile, iSectIndex, nMirror, bCheckFileSize, ++iAttempt);
01268 else
01269 return IR_S_FALSE;
01270 }
01271 else
01272 {
01273 if (ir == IR_EXTERROR)
01274 Event (DE_ERRFROMSERVER, (UINT) m_pOpeningFile->GetLastError ());
01275
01276 UINT nMirr = nMirror;
01277 if (nMirr == UINT_MAX && iSectIndex != -1)
01278 nMirr = m_vSections [iSectIndex].nMirrorURL;
01279
01280 if (nMirr != UINT_MAX)
01281 m_vMirrs [nMirr].bIsGood = FALSE;
01282 else if (m_vMirrs.size ())
01283 nMirr = 0;
01284
01285 if (nMirr != UINT_MAX)
01286 {
01287 if (UINT (iAttempt) < m_uMaxAttempts && iAttempt < 10)
01288 {
01289 nMirr = FindNotBusyMirrorIndex ();
01290
01291 if (nMirr != UINT_MAX && IsDone () == FALSE)
01292 {
01293 if (iSectIndex != -1)
01294 m_vSections [iSectIndex].nMirrorURL = nMirr;
01295
01296 nMirror = nMirr;
01297
01298 SAFE_DELETE (m_pOpeningFile);
01299 if (ir == IR_BADFILESIZE)
01300 Event (DE_BADFILESIZE);
01301 Event (DE_TRYINGANOTHERMIRROR);
01302 LeaveCriticalSection (&m_csOpenUrl);
01303 LOG ("fsID::OU_i: calling openurl again..." << nl);
01304 return OpenUrl_imp (uStartPos, ppFile, iSectIndex, nMirror, bCheckFileSize, ++iAttempt);
01305 }
01306 }
01307 }
01308 }
01309
01310 if (ir == IR_RANGESNOTAVAIL || ir == IR_DOUBTFUL_RANGESRESPONSE)
01311 {
01312 m_enRST = RST_NONE;
01313 m_bWasAccessedAtLeastOnce = TRUE;
01314 }
01315
01316 if (ir != IR_BADFILESIZE)
01317 {
01318 SAFE_DELETE (m_pOpeningFile);
01319 LeaveCriticalSection (&m_csOpenUrl);
01320 LOG ("fsID::OU_i: openurl failed" << nl);
01321 return ir;
01322 }
01323 }
01324
01325 *ppFile = m_pOpeningFile;
01326 m_enRST = m_enRST == RST_NONE ? RST_NONE : m_pOpeningFile->IsResumeSupported ();
01327 m_strSuggFileName = m_pOpeningFile->GetSuggestedFileName ();
01328 m_bWasAccessedAtLeastOnce = TRUE;
01329 m_pOpeningFile = NULL;
01330
01331 if (m_strContentType.Length () == 0)
01332 {
01333 char szContType [1000];
01334 if ((*ppFile)->GetContentType (szContType))
01335 m_strContentType = szContType;
01336 }
01337
01338 if (m_strFileName.Length () == 0)
01339 {
01340 if (m_strSuggFileName.Length ())
01341 m_strFileName = m_strSuggFileName;
01342 else
01343 {
01344 char szFile [10000];
01345 fsFileNameFromUrlPath (dnp->pszPathName, dnp->enProtocol == NP_FTP,
01346 TRUE, szFile, sizeof (szFile));
01347 m_strFileName = szFile;
01348 }
01349 }
01350
01351 (*ppFile)->GetLastModifiedDate (&m_fileDate);
01352
01353 LeaveCriticalSection (&m_csOpenUrl);
01354 LOG ("fsID::OU_i: openurl succeded" << nl);
01355 return IR_SUCCESS;
01356 }
01357
01358 void fsInternetDownloader::SetRetryTime(DWORD dwMilliseconds)
01359 {
01360 m_uRetryTime = dwMilliseconds;
01361 }
01362
01363 BOOL fsInternetDownloader::GetSectionInfo(int iSection, fsSection* pSection, BOOL bNoCacheAccounting)
01364 {
01365 if (iSection >= m_vSections.size ())
01366 return FALSE;
01367
01368 fsSectionEx *sect = &m_vSections [iSection];
01369 *pSection = *sect;
01370
01371 if (!bNoCacheAccounting)
01372 {
01373 pSection->uCurrent += sect->dwCacheLen;
01374 pSection->uDCurrent += sect->dwCacheLen;
01375 }
01376
01377 pSection->file = NULL;
01378
01379 return TRUE;
01380 }
01381
01382 BOOL fsInternetDownloader::SetSection_TrafficLimit(int iSection, UINT uLimit)
01383 {
01384 if (iSection >= m_vSections.size ())
01385 return FALSE;
01386
01387 m_vSections [iSection].uSpeedLimit = uLimit;
01388
01389 return TRUE;
01390 }
01391
01392 int fsInternetDownloader::GetNumberOfSections()
01393 {
01394 return m_vSections.size ();
01395 }
01396
01397 void fsInternetDownloader::SetSectionMinSize(UINT uMinSize)
01398 {
01399 m_uSectionMinSize = uMinSize;
01400 }
01401
01402 void fsInternetDownloader::StopDownloading()
01403 {
01404 m_bNeedStop = TRUE;
01405
01406 m_cThreads++;
01407
01408 try {
01409 if (m_pOpeningFile)
01410 {
01411 LOG ("fsID::SD: closing opening file (" << (DWORD)m_pOpeningFile << ")" << nl);
01412 m_pOpeningFile->CloseHandle ();
01413 }
01414 }catch (...) {}
01415
01416 try {
01417 if (m_pZipPreviewStream)
01418 m_pZipPreviewStream->Stop ();
01419 }catch (...) {}
01420
01421
01422 try{
01423 if (m_pMirrURLMgr)
01424 m_pMirrURLMgr->Abort ();
01425 }catch (...) {}
01426
01427 for (int i = 0; i < m_vSections.size (); i++)
01428 {
01429 fsSection *sect = &m_vSections [i];
01430 try{
01431 if (sect->file)
01432 sect->file->CloseHandle ();
01433 }catch (...) {ASSERT (FALSE);}
01434 }
01435
01436 m_cThreads--;
01437 }
01438
01439 BOOL fsInternetDownloader::SaveSectionsState(LPBYTE pBuffer, LPDWORD pdwSize)
01440 {
01441 DWORD dwNeedSize = sizeof (int) + m_vSections.size () * sizeof (fsSection);
01442
01443 dwNeedSize += sizeof (int) + m_strFileName.Length ();
01444 dwNeedSize += sizeof (DWORD);
01445 dwNeedSize += 2*sizeof (UINT64);
01446
01447 if (dwNeedSize == 0 || pBuffer == NULL)
01448 {
01449 *pdwSize = dwNeedSize;
01450 return TRUE;
01451 }
01452
01453 if (*pdwSize < dwNeedSize)
01454 {
01455 *pdwSize = dwNeedSize;
01456 return FALSE;
01457 }
01458
01459 *((LPINT)pBuffer) = m_vSections.size ();
01460 pBuffer += sizeof (INT);
01461
01462 fsSection* pBuf = (fsSection*) pBuffer;
01463
01464 for (int i = 0; i < m_vSections.size (); i++)
01465 {
01466 *pBuf++ = m_vSections [i];
01467 }
01468
01469 pBuffer = LPBYTE (pBuf);
01470 *((LPINT)pBuffer) = m_strFileName.Length ();
01471 pBuffer += sizeof (int);
01472 strncpy (LPSTR (pBuffer), m_strFileName, m_strFileName.Length ());
01473 pBuffer += m_strFileName.Length ();
01474
01475 *((LPDWORD)pBuffer) = m_dwState;
01476 pBuffer += sizeof (DWORD);
01477
01478 ((UINT64*)pBuffer) [0] = m_uSSFileSize;
01479 ((UINT64*)pBuffer) [1] = m_uLDFileSize;
01480 pBuffer += 2*sizeof (UINT64);
01481
01482 *pdwSize = dwNeedSize;
01483
01484 return TRUE;
01485 }
01486
01487 BOOL fsInternetDownloader::RestoreSectionsState(LPBYTE pBuffer, DWORD dwSize, DWORD dwVer)
01488 {
01489 if (dwVer < 5)
01490 return RestoreSectionsState_vlt5 (pBuffer, dwSize, dwVer);
01491
01492 if (dwVer == 5)
01493 return RestoreSectionsState_v5 (pBuffer, dwSize);
01494
01495 if (pBuffer == NULL || m_vSections.size ())
01496 return FALSE;
01497
01498 int cSects = *((LPINT) pBuffer);
01499 fsSection *pSects = (fsSection*) (pBuffer + sizeof (int));
01500
01501 for (int i = 0; i < cSects; i++)
01502 {
01503 ASSERT (pSects->iSection == i);
01504 if (pSects->iSection != i)
01505 return FALSE;
01506
01507 m_vSections.add (*pSects++);
01508
01509 fsSection *sect = &m_vSections [i];
01510
01511 sect->file = NULL;
01512 if (sect->state != SS_DONE)
01513 sect->state = SS_STOPPED;
01514
01515 sect->pThis = this;
01516 sect->uSpeed = 0;
01517 }
01518
01519 pBuffer = LPBYTE (pSects);
01520 int iStrLen = *((LPINT) pBuffer);
01521 pBuffer += sizeof (int);
01522
01523 if (iStrLen > MY_MAX_PATH || iStrLen < 0)
01524 return FALSE;
01525
01526 char sz [10000];
01527 strncpy (sz, LPCSTR (pBuffer), iStrLen);
01528 sz [iStrLen] = 0;
01529 m_strFileName = sz;
01530 pBuffer += iStrLen;
01531
01532 m_dwState = *((LPDWORD) pBuffer);
01533 pBuffer += sizeof (DWORD);
01534
01535 m_uSSFileSize = ((UINT64*) pBuffer) [0];
01536 m_uLDFileSize = ((UINT64*) pBuffer) [1];
01537 pBuffer += 2*sizeof (UINT64);
01538
01539
01540 if (m_vSections.size () == 1 && m_vSections [0].uDEnd == _UI64_MAX &&
01541 m_uLDFileSize != _UI64_MAX)
01542 m_vSections [0].uDEnd = m_uLDFileSize;
01543
01544 return TRUE;
01545 }
01546
01547 BOOL fsInternetDownloader::RestoreSectionsState_vlt5(LPBYTE pBuffer, DWORD dwSize, DWORD dwVer)
01548 {
01549 if (dwVer < 4)
01550 return RestoreSectionsState_vlt4 (pBuffer, dwSize);
01551
01552 if (pBuffer == NULL || m_vSections.size ())
01553 return FALSE;
01554
01555 int cSects = *((LPINT) pBuffer);
01556 fsSection_v2 *pSects = (fsSection_v2*) (pBuffer + sizeof (int));
01557
01558 for (int i = 0; i < cSects; i++)
01559 {
01560 fsSection section;
01561 section = *pSects++;
01562
01563 m_vSections.add (section);
01564
01565 fsSection *sect = &m_vSections [i];
01566
01567 sect->file = NULL;
01568 if (sect->state != SS_DONE)
01569 sect->state = SS_STOPPED;
01570
01571 sect->pThis = this;
01572 sect->uSpeed = 0;
01573 }
01574
01575 pBuffer = LPBYTE (pSects);
01576 int iStrLen = *((LPINT) pBuffer);
01577 pBuffer += sizeof (int);
01578
01579 if (iStrLen > MY_MAX_PATH || iStrLen < 0)
01580 return FALSE;
01581
01582 char sz [10000];
01583 strncpy (sz, LPCSTR (pBuffer), iStrLen);
01584 sz [iStrLen] = 0;
01585 m_strFileName = sz;
01586 pBuffer += iStrLen;
01587
01588 m_dwState = *((LPDWORD) pBuffer);
01589 pBuffer += sizeof (DWORD);
01590
01591 m_uSSFileSize = 0;
01592 while (cSects--)
01593 m_uSSFileSize = max (m_uSSFileSize, m_vSections [cSects].uEnd);
01594 m_uLDFileSize = m_uSSFileSize;
01595
01596 return TRUE;
01597 }
01598
01599 BOOL fsInternetDownloader::RestoreSectionsState_vlt4(LPVOID pBuffer, DWORD dwSize)
01600 {
01601 if (pBuffer == NULL || dwSize % sizeof (fsSection_v1) || m_vSections.size ())
01602 return FALSE;
01603
01604 fsSection_v1 *pSects = (fsSection_v1*) pBuffer;
01605
01606 for (UINT i = 0; i < dwSize / sizeof (fsSection_v1); i++)
01607 {
01608 fsSection section;
01609 section = *pSects++;
01610
01611 m_vSections.add (section);
01612
01613 fsSection *sect = &m_vSections [i];
01614
01615 sect->file = NULL;
01616 if (sect->state != SS_DONE)
01617 sect->state = SS_STOPPED;
01618
01619 sect->pThis = this;
01620 sect->uSpeed = 0;
01621 }
01622
01623 int cSects = m_vSections.size ();
01624
01625 m_uSSFileSize = 0;
01626 while (cSects--)
01627 m_uSSFileSize = max (m_uSSFileSize, m_vSections [cSects].uEnd);
01628 m_uLDFileSize = m_uSSFileSize;
01629
01630 return TRUE;
01631 }
01632
01633 fsInternetResult fsInternetDownloader::StartDownloading(UINT uStartFrom)
01634 {
01635 int size = m_vSections.size ();
01636
01637 m_speed.Reset ();
01638 m_dwDataLenInCache = 0;
01639
01640 if (size == 0)
01641 return CreateMainSection (uStartFrom);
01642
01643 if (IsRunning () || IsDone ())
01644 return IR_S_FALSE;
01645
01646 m_bNeedStop = FALSE;
01647
01648 if (m_vMirrs.size () == 0)
01649 Auto_SearchMirrors ();
01650
01651 DWORD dwThread;
01652 BOOL bQS = TRUE;
01653 BOOL bAtLeast1Started = FALSE;
01654
01655 m_bNoNewSections = TRUE;
01656
01657
01658 int nSC = GetNumberOfSections () - GetDoneSectionCount ();
01659 if (nSC)
01660
01661 #ifndef FDM_DLDR__RAWCODEONLY
01662 m_dwForceCacheSizePerSection = _App.FileWriteCacheSize () / nSC;
01663 #else
01664 m_dwForceCacheSizePerSection = 0;
01665 #endif
01666
01667
01668 for (int i = 0; i < size && m_bNeedStop == FALSE; i++)
01669 {
01670 fsSection § = m_vSections [i];
01671
01672 if (sect.state == SS_DONE)
01673 continue;
01674
01675 if (bQS)
01676 {
01677 if (Event (DE_QUERYNEWSECTION, sect.nMirrorURL) == FALSE)
01678 continue;
01679 }
01680 else
01681 bQS = TRUE;
01682
01683 sect.file = NULL;
01684
01685 UINT nMirrorInc = sect.nMirrorURL;
01686 if (nMirrorInc == UINT_MAX)
01687 m_cBaseSectCreatingNow++;
01688 else
01689 m_vMirrs [nMirrorInc].cSectsCreatingNow++;
01690
01691 sect.lastErr = OpenUrl (sect.uCurrent, §.file, -1, sect.nMirrorURL, TRUE);
01692 if (sect.lastErr == IR_SUCCESS)
01693 {
01694 bAtLeast1Started = TRUE;
01695
01696 if (Event (DE_NEEDFILE) == FALSE || FALSE == Event (DE_NEEDFILE_FINALINITIALIZATION))
01697 return IR_S_FALSE;
01698 }
01699 else if (bAtLeast1Started)
01700 {
01701
01702 if (nMirrorInc == UINT_MAX)
01703 m_cBaseSectCreatingNow--;
01704 else
01705 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01706
01707 continue;
01708 }
01709
01710 switch (sect.lastErr)
01711 {
01712 case IR_RANGESNOTAVAIL:
01713 case IR_DOUBTFUL_RANGESRESPONSE:
01714 if (m_bDontRestartIfNoRanges)
01715 {
01716 if (nMirrorInc == UINT_MAX)
01717 m_cBaseSectCreatingNow--;
01718 else
01719 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01720 return sect.lastErr;
01721 }
01722 else
01723 {
01724 Event (DE_RESTARTINGBECAUSENORANGES);
01725 StopDownloading ();
01726 while (IsRunning ())
01727 Sleep (5);
01728 m_vSections.clear ();
01729 if (nMirrorInc == UINT_MAX)
01730 m_cBaseSectCreatingNow--;
01731 else
01732 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01733 return StartDownloading ();
01734 }
01735 break;
01736
01737 case IR_FILENOTFOUND:
01738 if (m_bStopOnFileNotFound)
01739 {
01740 if (nMirrorInc == UINT_MAX)
01741 m_cBaseSectCreatingNow--;
01742 else
01743 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01744 return IR_FILENOTFOUND;
01745 }
01746 break;
01747
01748 case IR_LOGINFAILURE:
01749 case IR_INVALIDPASSWORD:
01750 case IR_INVALIDUSERNAME:
01751 if (m_bStopOnAccDenied)
01752 {
01753 if (nMirrorInc == UINT_MAX)
01754 m_cBaseSectCreatingNow--;
01755 else
01756 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01757 return IR_LOGINFAILURE;
01758 }
01759 break;
01760 }
01761
01762 if (sect.lastErr != IR_BADFILESIZE && sect.file == NULL && bAtLeast1Started == FALSE)
01763 {
01764 fsInternetResult ir = OpenUrl (0, §.file, -1, sect.nMirrorURL, TRUE);
01765 if (ir == IR_SUCCESS)
01766 {
01767 if (sect.file->GetFileSize () != m_uSSFileSize)
01768 sect.lastErr = IR_BADFILESIZE;
01769 else
01770 {
01771 delete sect.file;
01772 sect.file = NULL;
01773 }
01774 }
01775 }
01776
01777 if (sect.lastErr == IR_BADFILESIZE)
01778 {
01779 UINT64 uNewSize = sect.file->GetFileSize ();
01780
01781 if (m_uSSFileSize != uNewSize)
01782 {
01783 UINT64 u = m_uSSFileSize;
01784 m_uSSFileSize = uNewSize;
01785
01786
01787 DWORD dwSCR = Event (DE_SCR);
01788
01789 m_uSSFileSize = u;
01790
01791 switch (dwSCR)
01792 {
01793 case SCR_RESTART:
01794 SAFE_DELETE (sect.file);
01795 m_vSections.clear ();
01796 if (nMirrorInc == UINT_MAX)
01797 m_cBaseSectCreatingNow--;
01798 else
01799 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01800 return StartDownloading ();
01801
01802 case SCR_STOP:
01803 SAFE_DELETE (sect.file);
01804 if (nMirrorInc == UINT_MAX)
01805 m_cBaseSectCreatingNow--;
01806 else
01807 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01808 return IR_S_FALSE;
01809
01810 case SCR_ADJUSTFORNEWSIZE:
01811
01812 if (m_uSSFileSize > uNewSize)
01813 {
01814
01815 for (int i = 0; i < size; i++)
01816 {
01817 fsSection § = m_vSections [i];
01818
01819 if (sect.uEnd > uNewSize)
01820 {
01821 EnterCriticalSection (&m_csSections);
01822 sect.uEnd = sect.uDEnd = uNewSize;
01823 if (sect.uCurrent > sect.uEnd)
01824 {
01825 sect.uCurrent = sect.uDCurrent = sect.uEnd;
01826 sect.state = SS_DONE;
01827 }
01828 LeaveCriticalSection (&m_csSections);
01829 }
01830 }
01831 }
01832 else for (int i = 0; i < size; i++)
01833 {
01834
01835 if (m_vSections [i].uEnd == m_uSSFileSize)
01836 {
01837 m_vSections [i].uEnd = uNewSize;
01838 break;
01839 }
01840 }
01841 SAFE_DELETE (sect.file);
01842 i--;
01843 m_uSSFileSize = uNewSize;
01844 bQS = FALSE;
01845 if (nMirrorInc == UINT_MAX)
01846 m_cBaseSectCreatingNow--;
01847 else
01848 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01849 continue;
01850
01851 default:
01852 ASSERT (FALSE);
01853 if (nMirrorInc == UINT_MAX)
01854 m_cBaseSectCreatingNow--;
01855 else
01856 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01857 return IR_S_FALSE;
01858 }
01859 }
01860 }
01861
01862 if (nMirrorInc == UINT_MAX)
01863 m_cBaseSectCreatingNow--;
01864 else
01865 m_vMirrs [nMirrorInc].cSectsCreatingNow--;
01866
01867 if (sect.file == NULL && bAtLeast1Started == FALSE)
01868 return sect.lastErr;
01869
01870 m_cThreads++; m_cRunningThreads++;
01871 Event (DE_SECTIONSTARTED, i);
01872 m_vSections [i].state = SS_DOWNLOADING;
01873 CloseHandle (CreateThread (NULL, 0, _threadDownload, &m_vSections [i], 0, &dwThread));
01874 }
01875
01876 m_bNoNewSections = FALSE;
01877 m_dwForceCacheSizePerSection = DWORD (-1);
01878 return IsRunning () ? IR_SUCCESS : IR_S_FALSE;
01879 }
01880
01881 BOOL fsInternetDownloader::IsDownloading()
01882 {
01883 for (int i = 0; i < m_vSections.size (); i++)
01884 {
01885 if (m_vSections [i].state == SS_DOWNLOADING)
01886 return TRUE;
01887 }
01888
01889 return FALSE;
01890 }
01891
01892 void fsInternetDownloader::LimitTraffic(UINT uLimit)
01893 {
01894 m_uTrafficLimit = uLimit;
01895
01896 UpdateTrafficLimit ();
01897 }
01898
01899 UINT fsInternetDownloader::GetSpeed()
01900 {
01901 return m_speed.GetSpeed ();
01902 }
01903
01904 void fsInternetDownloader::SetEventFunc(fsDownloaderEventFunc pfn, LPVOID lpParam)
01905 {
01906 m_pfnEvents = pfn;
01907 m_lpEvent = lpParam;
01908 }
01909
01910 DWORD fsInternetDownloader::Event(fsDownloaderEvent enEvent, UINT uDesc)
01911 {
01912 if (m_pfnEvents)
01913 return m_pfnEvents (enEvent, uDesc, m_lpEvent);
01914
01915 return TRUE;
01916 }
01917
01918 void fsInternetDownloader::SetMaxReconnectionNumber(UINT uMax)
01919 {
01920 m_uMaxAttempts = uMax;
01921 }
01922
01923 UINT64 fsInternetDownloader::GetSectionMaxSize()
01924 {
01925 int size = m_vSections.size ();
01926 UINT64 uMax = 0;
01927
01928 for (int i = 0; i < size; i++)
01929 {
01930 UINT64 uD = m_vSections [i].uEnd - m_vSections [i].uCurrent;
01931
01932 if (uMax < uD)
01933 uMax = uD;
01934 }
01935
01936 return uMax;
01937 }
01938
01939 BOOL fsInternetDownloader::IsDone()
01940 {
01941 int size = m_vSections.size ();
01942
01943 for (int i = 0; i < size; i++)
01944 {
01945 if (m_vSections [i].state != SS_DONE)
01946 return FALSE;
01947 }
01948
01949 return size != 0;
01950 }
01951
01952 BOOL fsInternetDownloader::IsStoppedByUser()
01953 {
01954 return m_bNeedStop;
01955 }
01956
01957 BOOL fsInternetDownloader::IsHavingError()
01958 {
01959 return m_bErrDownloading;
01960 }
01961
01962 fsInternetResult fsInternetDownloader::GetSectionLastError(int iSection)
01963 {
01964 return m_vSections [iSection].lastErr;
01965 }
01966
01967 BOOL fsInternetDownloader::SleepInterval()
01968 {
01969 int i = m_uRetryTime;
01970
01971 while (i > 0)
01972 {
01973 Sleep (100);
01974 i -= 100;
01975
01976 if (m_bNeedStop)
01977 return FALSE;
01978 }
01979
01980 return TRUE;
01981 }
01982
01983 BOOL fsInternetDownloader::IsRunning()
01984 {
01985 return m_cRunningThreads > 0;
01986 }
01987
01988 UINT64 fsInternetDownloader::GetSSFileSize()
01989 {
01990 return m_uSSFileSize;
01991 }
01992
01993 int fsInternetDownloader::GetRunningSectionCount()
01994 {
01995 return m_cRunningThreads;
01996 }
01997
01998 BOOL fsInternetDownloader::IsAllSectionsOk()
01999 {
02000 int cSections = m_vSections.size ();
02001
02002 for (int i = 0; i < cSections; i++)
02003 {
02004 fsSectionState state = m_vSections [i].state;
02005
02006 if (state != SS_DOWNLOADING && state != SS_DONE)
02007 return FALSE;
02008 }
02009
02010 return TRUE;
02011 }
02012
02013 int fsInternetDownloader::GetDownloadingSectionCount()
02014 {
02015 m_vSections.lock ();
02016
02017 int cSections = m_vSections.size ();
02018 int cDlding = 0;
02019
02020 for (int i = 0; i < cSections; i++)
02021 if (m_vSections [i].state == SS_DOWNLOADING)
02022 cDlding++;
02023
02024 m_vSections.unlock ();
02025
02026 return cDlding;
02027 }
02028
02029 void fsInternetDownloader::UpdateTrafficLimit()
02030 {
02031 UINT nSections = m_vSections.size ();
02032 UINT nGoodSects = GetDownloadingSectionCount ();
02033
02034 if (nGoodSects == 0)
02035 return;
02036
02037 for (UINT i = 0; i < nSections; i++)
02038 {
02039 m_vSections [i].uSpeedLimit = m_uTrafficLimit / nGoodSects;
02040 }
02041 }
02042
02043 void fsInternetDownloader::ApplyProperties(fsInternetURLFile *pFile, fsDownload_NetworkProperties* dnp)
02044 {
02045
02046 if (*dnp->pszReferer == 0 && (dnp->enProtocol == NP_HTTP || dnp->enProtocol == NP_HTTPS))
02047 {
02048 char szUrl [10000];
02049 char szRefUrl [10000];
02050 fsURL url;
02051 DWORD dw = sizeof (szUrl);
02052 if (*dnp->pszPathName && strcmp (dnp->pszPathName, "/") && strcmp (dnp->pszPathName, "\\") &&
02053 IR_SUCCESS == url.Create (fsNPToScheme (dnp->enProtocol), dnp->pszServerName, dnp->uServerPort, NULL, NULL, dnp->pszPathName,
02054 szUrl, &dw))
02055 {
02056 if (fsFilePathFromUrlPath (szUrl, dnp->enProtocol == NP_FTP,
02057 FALSE, szRefUrl, sizeof (szRefUrl)))
02058 {
02059 LPSTR psz1 = strrchr (szRefUrl, '\\');
02060 LPSTR psz2 = strrchr (szRefUrl, '/');
02061 if (psz2 > psz1)
02062 psz1 = psz2;
02063
02064 if (psz1)
02065 {
02066 *(psz1+1) = 0;
02067 pFile->SetReferer (szRefUrl);
02068 }
02069 }
02070 }
02071 }
02072 else
02073 pFile->SetReferer (dnp->pszReferer);
02074
02075 pFile->UseHttp11 (dnp->bUseHttp11);
02076 pFile->UseCookie (dnp->bUseCookie);
02077 pFile->SetCookies (dnp->pszCookies);
02078 pFile->SetPostData (dnp->pszPostData);
02079 pFile->UseFtpPassiveMode (dnp->dwFtpFlags & FTP_USEPASSIVEMODE);
02080 pFile->FtpSetDontUseLIST (dnp->dwFtpFlags & FTP_DONTSENDLIST);
02081
02082 if (dnp->enFtpTransferType != FTT_UNKNOWN && dnp->enProtocol == NP_FTP)
02083 pFile->FtpSetTransferType (dnp->enFtpTransferType);
02084 }
02085
02086 int fsInternetDownloader::GetDoneSectionCount()
02087 {
02088 int cSections = m_vSections.size ();
02089 int cDlding = 0;
02090
02091 for (int i = 0; i < cSections; i++)
02092 if (m_vSections [i].state == SS_DONE)
02093 cDlding++;
02094
02095 return cDlding;
02096 }
02097
02098 UINT64 fsInternetDownloader::GetBytesLeft()
02099 {
02100 UINT64 uLeft = 0;
02101 int cSections = m_vSections.size ();
02102
02103 for (int i = cSections - 1; i >= 0; i--)
02104 {
02105 fsSection *sect = &m_vSections [i];
02106
02107 if (sect->uDEnd == _UI64_MAX)
02108 return _UI64_MAX;
02109
02110 if (sect->uDEnd > sect->uDCurrent)
02111 uLeft += sect->uDEnd - sect->uDCurrent;
02112 }
02113
02114 return uLeft - m_dwDataLenInCache;
02115 }
02116
02117 void fsInternetDownloader::SetOutputFile(HANDLE hOutFile)
02118 {
02119 m_hOutFile = hOutFile;
02120 }
02121
02122 void fsInternetDownloader::ResetSections()
02123 {
02124 StopDownloading ();
02125 while (m_cThreads)
02126 Sleep (5);
02127 m_vSections.clear ();
02128 }
02129
02130 void fsInternetDownloader::DontRestartIfNoRanges(BOOL b)
02131 {
02132 m_bDontRestartIfNoRanges = b;
02133 }
02134
02135 void fsInternetDownloader::StopOnFileNotFound(BOOL b)
02136 {
02137 m_bStopOnFileNotFound = b;
02138 }
02139
02140 void fsInternetDownloader::StopOnAccDenied(BOOL b)
02141 {
02142 m_bStopOnAccDenied = b;
02143 }
02144
02145 UINT fsInternetDownloader::GetTrafficLimit()
02146 {
02147 return m_uTrafficLimit;
02148 }
02149
02150 fsResumeSupportType fsInternetDownloader::IsResumeSupported()
02151 {
02152 return m_enRST;
02153 }
02154
02155 float fsInternetDownloader::GetPercentDone()
02156 {
02157 UINT64 uDone = 0, uSize = GetLDFileSize ();
02158
02159 UINT64 uBytesLeft = GetBytesLeft ();
02160
02161 if (uSize != _UI64_MAX)
02162 uDone = uSize - uBytesLeft;
02163
02164 return uSize ? float ((double)(INT64)uDone / (INT64)uSize * 100.0f) : 0;
02165 }
02166
02167 int fsInternetDownloader::GetCreatingNowSectionCount(UINT nMirror)
02168 {
02169 if (m_cBaseSectCreatingNow < 0)
02170 m_cBaseSectCreatingNow = 0;
02171
02172 if (nMirror == UINT_MAX)
02173 return m_cBaseSectCreatingNow != 0;
02174 else
02175 return m_vMirrs [nMirror].cSectsCreatingNow != 0;
02176 }
02177
02178 void fsInternetDownloader::DeleteAllSections()
02179 {
02180 if (IsRunning ())
02181 return;
02182
02183 m_vSections.clear ();
02184 RemoveAllMirrors ();
02185
02186 m_dwState &= ~ IDS_ZIPPREVIEWPERFORMED;
02187
02188 m_uSSFileSize = m_uLDFileSize = 0;
02189 }
02190
02191 void fsInternetDownloader::StopSection()
02192 {
02193 fsSection *sectErr = NULL, *sectDl = NULL;
02194 UINT64 errMax = 0, dlMax = 0;
02195
02196 for (int i = 0; i < m_vSections.size (); i++)
02197 {
02198 fsSection *sect = &m_vSections [i];
02199
02200 if (sect->state == SS_ERROR || sect->state == SS_RECONNECTING || sect->state == SS_WRITEERROR)
02201 {
02202 if ((sect->uEnd - sect->uCurrent) > errMax)
02203 {
02204 sectErr = sect;
02205 errMax = sect->uEnd - sect->uCurrent;
02206 }
02207 }
02208 else if (sect->state == SS_DOWNLOADING)
02209 {
02210 if ((sect->uEnd - sect->uCurrent) > dlMax)
02211 {
02212 sectDl = sect;
02213 dlMax = sect->uEnd - sect->uCurrent;
02214 }
02215 }
02216 }
02217
02218
02219 if (sectErr)
02220 {
02221
02222 sectErr->state = SS_NEEDSTOP;
02223 }
02224 else if (sectDl)
02225 {
02226
02227 sectDl->state = SS_NEEDSTOP;
02228 }
02229 }
02230
02231 LPCSTR fsInternetDownloader::GetSuggestedFileName()
02232 {
02233 return m_strSuggFileName.Length () ? m_strSuggFileName : NULL ;
02234 }
02235
02236 fsInternetResult fsInternetDownloader::QuerySize()
02237 {
02238 if (IsRunning ())
02239 return IR_S_FALSE;
02240
02241 EnterCriticalSection (&m_csAddSection);
02242 EnterCriticalSection (&m_csOpenUrl);
02243
02244 if (m_pOpeningFile)
02245 {
02246 LeaveCriticalSection (&m_csAddSection);
02247 LeaveCriticalSection (&m_csOpenUrl);
02248 return IR_S_FALSE;
02249 }
02250
02251 fsInternetURLFile file;
02252 m_pOpeningFile = &file;
02253 m_pOpeningFile->SetDialogFunc (_InetFileDialogFunc, this, NULL);
02254
02255 fsInternetResult ir = QuerySize (&file);
02256
02257 m_pOpeningFile = NULL;
02258 if (ir != IR_SUCCESS)
02259 {
02260 LeaveCriticalSection (&m_csAddSection);
02261 LeaveCriticalSection (&m_csOpenUrl);
02262 return ir;
02263 }
02264
02265 m_uSSFileSize = m_uLDFileSize = file.GetFileSize ();
02266
02267 if (m_vSections.size () == 0)
02268 {
02269
02270 fsSection sect;
02271 sect.uStart = sect.uDStart = 0;
02272 sect.uCurrent = sect.uDCurrent = 0;
02273 sect.uEnd = sect.uDEnd = m_uSSFileSize;
02274 sect.file = NULL;
02275
02276 CreateSection (sect, FALSE);
02277 }
02278
02279 LeaveCriticalSection (&m_csAddSection);
02280 LeaveCriticalSection (&m_csOpenUrl);
02281 return IR_SUCCESS;
02282 }
02283
02284 fsInternetResult fsInternetDownloader::QuerySize(fsInternetURLFile *file)
02285 {
02286 fsInternetResult ir;
02287
02288 vmsInternetSession* pSession = new vmsInternetSession;
02289 char szProxy [10000];
02290 vmsMakeWinInetProxy (DNP ()->pszProxyName, DNP ()->enProtocol, DNP ()->enProtocol, szProxy);
02291 ir = pSession->Create (DNP ()->pszAgent, DNP ()->enAccType, szProxy, DNP ()->enProtocol);
02292 if (ir != IR_SUCCESS)
02293 return ir;
02294 ApplyProxySettings (pSession, DNP ());
02295
02296 ir = file->Initialize (pSession, TRUE);
02297 if (ir != IR_SUCCESS)
02298 return ir;
02299
02300 ApplyProperties (file, DNP ());
02301
02302 ir = file->QuerySize (fsNPToScheme (DNP ()->enProtocol), DNP ()->pszServerName,
02303 DNP ()->pszUserName, DNP ()->pszPassword, DNP ()->uServerPort, DNP ()->pszPathName,
02304 DNP ()->dwFlags & DNPF_IMMEDIATELY_SEND_AUTH_AS_BASIC);
02305
02306 if (ir != IR_SUCCESS)
02307 {
02308 if (ir == IR_NEEDREDIRECT)
02309 {
02310 if (m_vSections.size ())
02311 return IR_SERVERUNKERROR;
02312
02313 LPCSTR pszUrl = file->GetLastError ();
02314
02315 fsURL url;
02316 CHAR szUrl [10000];
02317 DWORD dwLen = sizeof (szUrl);
02318
02319 if (url.Crack (pszUrl) != IR_SUCCESS)
02320 {
02321 char szUrlPath [10000];
02322
02323 if (*pszUrl == 0)
02324 strcpy (szUrlPath, "/");
02325 else if (*pszUrl != '/' && *pszUrl != '\\')
02326 {
02327 fsPathFromUrlPath (DNP()->pszPathName, DNP()->enProtocol == NP_FTP, FALSE, szUrlPath, 10000);
02328
02329 if (szUrlPath [lstrlen (szUrlPath)-1] != '\\' &&
02330 szUrlPath [lstrlen (szUrlPath)-1] != '/')
02331 lstrcat (szUrlPath, "\\");
02332
02333 strcat (szUrlPath, pszUrl);
02334 }
02335 else
02336 strcpy (szUrlPath, pszUrl);
02337
02338 url.Create (fsNPToScheme (DNP ()->enProtocol), DNP ()->pszServerName, DNP ()->uServerPort,
02339 DNP ()->pszUserName, DNP ()->pszPassword, szUrlPath, szUrl, &dwLen);
02340 }
02341 else
02342 strcpy (szUrl, pszUrl);
02343
02344 ir = fsDNP_ApplyUrl (DNP (), szUrl);
02345
02346 if (ir != IR_SUCCESS)
02347 return ir;
02348
02349 if (m_bNeedStop == FALSE)
02350 return QuerySize (file);
02351 else
02352 return IR_S_FALSE;
02353 }
02354 else if (ir == IR_EXTERROR)
02355 {
02356
02357 }
02358
02359 return ir;
02360 }
02361
02362 m_bWasAccessedAtLeastOnce = TRUE;
02363 m_enRST = m_enRST == RST_NONE ? RST_NONE : file->IsResumeSupported ();
02364 m_strSuggFileName = file->GetSuggestedFileName ();
02365
02366 if (m_strFileName.Length () == 0)
02367 {
02368 if (m_strSuggFileName.Length ())
02369 m_strFileName = m_strSuggFileName;
02370 else
02371 {
02372 char szFile [10000];
02373 fsFileNameFromUrlPath (DNP ()->pszPathName, DNP ()->enProtocol == NP_FTP,
02374 TRUE, szFile, sizeof (szFile));
02375 m_strFileName = szFile;
02376 }
02377 }
02378
02379 return IR_SUCCESS;
02380 }
02381
02382 int fsInternetDownloader::GetStoppedSectionCount()
02383 {
02384 int cStopped = 0;
02385
02386 for (int i = 0; i < m_vSections.size (); i++)
02387 if (m_vSections [i].state == SS_STOPPED)
02388 cStopped++;
02389
02390 return cStopped;
02391 }
02392
02393 fsInternetResult fsInternetDownloader::LaunchOneMoreSection()
02394 {
02395 for (int i = 0; i < m_vSections.size (); i++)
02396 {
02397 if (m_vSections [i].state == SS_STOPPED)
02398 {
02399 m_vSections [i].file = NULL;
02400 m_cThreads++; m_cRunningThreads++;
02401 DWORD dwThread;
02402 Event (DE_SECTIONSTARTED, i);
02403 CloseHandle (CreateThread (NULL, 0, _threadDownload, &m_vSections [i], 0, &dwThread));
02404 return IR_SUCCESS;
02405 }
02406 }
02407
02408 return IR_S_FALSE;
02409 }
02410
02411 void fsInternetDownloader::_InetFileDialogFunc(fsInetFileDialogDirection dir, LPCSTR pszMsg, LPVOID lp1, LPVOID lp2)
02412 {
02413 fsInternetDownloader* pThis = (fsInternetDownloader*) lp1;
02414 int sect = (int) lp2;
02415
02416 if (pThis->m_bDetLog)
02417 {
02418 fsDlgWithServerInfo info;
02419 info.dir = dir;
02420 info.pszMsg = pszMsg;
02421 info.iSection = sect;
02422 pThis->Event (DE_DIALOGWITHSERVER, UINT (&info));
02423 }
02424 }
02425
02426 void fsInternetDownloader::UseDetailedLog(BOOL b)
02427 {
02428 m_bDetLog = b;
02429 }
02430
02431 fsDownload_NetworkProperties* fsInternetDownloader::MirrorDNP(int iMirror)
02432 {
02433 return &m_vMirrs [iMirror].dnp;
02434 }
02435
02436 int fsInternetDownloader::GetMirrorURLCount()
02437 {
02438 return m_vMirrs.size ();
02439 }
02440
02441 fsInternetResult fsInternetDownloader::AddMirrorURL(LPCSTR pszUrl, LPCSTR pszUser, LPCSTR pszPassword, BOOL bDontMeasureSpeed)
02442 {
02443 fsInternetResult ir;
02444
02445 fsDownload_NetworkProperties dnp;
02446 fsDNP_BuffersInfo buffs;
02447
02448 ZeroMemory (&dnp, sizeof (dnp));
02449
02450 ir = fsDNP_GetByUrl (&dnp, &buffs, TRUE, pszUrl);
02451
02452 if (ir != IR_SUCCESS)
02453 return ir;
02454
02455 fsDNP_CloneSettings (&dnp, DNP ());
02456
02457 if (pszUser)
02458 {
02459 SAFE_DELETE_ARRAY (dnp.pszUserName);
02460 SAFE_DELETE_ARRAY (dnp.pszPassword);
02461
02462 dnp.pszUserName = new char [strlen (pszUser) + 1];
02463 strcpy (dnp.pszUserName, pszUser);
02464
02465 dnp.pszPassword = new char [pszPassword ? strlen (pszPassword) + 1 : 1];
02466 strcpy (dnp.pszPassword, pszPassword ? pszPassword : "");
02467 }
02468
02469 AddMirror (&dnp, TRUE, bDontMeasureSpeed);
02470
02471 return IR_SUCCESS;
02472 }
02473
02474 fsInternetResult fsInternetDownloader::FindMirrors()
02475 {
02476 m_cMirrsFound = 0;
02477
02478 if (m_dwState & IDS_MIRRSEARCHPERFORMED)
02479 return IR_SUCCESS;
02480
02481 char szFileName [10000];
02482
02483 if (m_strFileName.Length () == 0)
02484 {
02485 fsFileNameFromUrlPath (DNP ()->pszPathName, DNP ()->enProtocol == NP_FTP, TRUE,
02486 szFileName, sizeof (szFileName));
02487 }
02488 else
02489 strcpy (szFileName, m_strFileName);
02490
02491 fsMirrorURLsMgr_FileMirrorsDotCom mirrors;
02492 #ifndef FDM_DLDR__RAWCODEONLY
02493 mirrors.Set_SearchURL (_App.Mirr_Server ());
02494 #else
02495 mirrors.Set_SearchURL (0);
02496 #endif
02497
02498 Event (DE_STARTINGSEARCHINGFORMIRRORS);
02499
02500 mirrors.Set_EventFunc (_MirrMgrEvents, this);
02501
02502 vmsInternetSession* pSession = new vmsInternetSession;
02503 char szProxy [10000];
02504 vmsMakeWinInetProxy (DNP ()->pszProxyName, DNP ()->enProtocol, DNP ()->enProtocol, szProxy);
02505 fsInternetResult ir = pSession->Create (DNP()->pszAgent, DNP()->enAccType, szProxy, DNP ()->enProtocol);
02506 if (ir != IR_SUCCESS)
02507 {
02508 delete pSession;
02509 Event (DE_MIRRFAILED);
02510 return ir;
02511 }
02512
02513 ApplyProxySettings (pSession, DNP());
02514
02515 mirrors.Initialize (szFileName, GetSSFileSize (), DNP ()->pszServerName,
02516 pSession);
02517
02518 ir = mirrors.SearchForMirrors ();
02519 if (ir != IR_SUCCESS)
02520 {
02521 delete pSession;
02522 Event (DE_MIRRFAILED);
02523 return ir;
02524 }
02525
02526 m_dwState |= IDS_MIRRSEARCHPERFORMED;
02527
02528 LOG ("adding mirrors to ID..." << nl);
02529
02530 for (int i = 0; i < mirrors.Get_MirrorURLCount () && UINT (i) < m_cMaxMirrs; i++)
02531 {
02532 AddMirrorURL (mirrors.Get_MirrorURL (i), NULL, NULL, TRUE);
02533 m_cMirrsFound++;
02534 }
02535
02536 LOG ("ok." << nl);
02537
02538 if (m_cMirrsFound && m_bNeedStop == FALSE)
02539 {
02540 Event (DE_MIRRFOUND);
02541 if (m_bMirrMeasureSpeed)
02542 {
02543 Event (DE_MEASURINGMIRRSPEED);
02544 MeasureMirrorsSpeed ();
02545 }
02546 Event (DE_MIRRDONE);
02547 }
02548 else
02549 Event (DE_NOMIRRFOUND);
02550
02551 delete pSession;
02552 return IR_SUCCESS;
02553 }
02554
02555 void fsInternetDownloader::Set_SearchForMirrors(BOOL bSearch)
02556 {
02557 m_bSearchForMirrors = bSearch;
02558 }
02559
02560 void fsInternetDownloader::_MirrMgrEvents(fsMirrorURLsMgrEvent ev, LPVOID lp)
02561 {
02562 fsInternetDownloader* pThis = (fsInternetDownloader*) lp;
02563
02564 switch (ev)
02565 {
02566 case MUME_CONNECTINGSEARCHSERVER:
02567 pThis->Event (DE_CONNECTINGMIRRSERVER);
02568 break;
02569
02570 case MUME_RETREIVINGSEARCHRESULTS:
02571 pThis->Event (DE_GETTINGMIRRSEARCHRESULTS);
02572 break;
02573 }
02574 }
02575
02576 UINT fsInternetDownloader::FindNotBusyMirrorIndex()
02577 {
02578 if (m_vMirrs.size () == 0)
02579 return UINT_MAX;
02580
02581 int cMirrs = m_vMirrs.size ();
02582
02583
02584 double *pfWeight = new double [cMirrs];
02585
02586
02587 for (int i = 0; i < cMirrs; i++)
02588 pfWeight [i] = 1;
02589
02590 for (i = 0; i < m_vSections.size (); i++)
02591 {
02592 if (m_vSections [i].nMirrorURL != UINT_MAX)
02593 pfWeight [m_vSections [i].nMirrorURL]++;
02594 }
02595
02596 for (i = 0; i < cMirrs; i++)
02597 {
02598 DWORD dwPingTime = m_vMirrs [i].dwPingTime;
02599 if (dwPingTime == UINT_MAX)
02600 dwPingTime = 50000;
02601
02602 pfWeight [i] = 1.0 /
02603 (pfWeight [i] * pow (double (dwPingTime) / 1000.0f, 2));
02604 }
02605
02606 double fMax = -1;
02607 int iMax = -1;
02608
02609 for (i = 0; i < cMirrs; i++)
02610 {
02611 if (pfWeight [i] > fMax && m_vMirrs [i].bIsGood)
02612 {
02613 fMax = pfWeight [i];
02614 iMax = i;
02615 }
02616 }
02617
02618 delete [] pfWeight;
02619
02620 return iMax;
02621 }
02622
02623 BOOL fsInternetDownloader::MeasureMirrorsSpeed()
02624 {
02625 fsSitePingMgr pinger;
02626
02627 m_bNeedStop = FALSE;
02628
02629 LOG ("measuring mirrors speed..." << nl);
02630
02631 if (pinger.TestState () == FALSE)
02632 {
02633 LOG ("failed to measure." << nl);
02634 return FALSE;
02635 }
02636
02637 m_dwBaseServerPingTime = pinger.Ping (DNP ()->pszServerName);
02638
02639 for (int i = 0; i < m_vMirrs.size (); i++)
02640 {
02641 if (m_bNeedStop)
02642 return FALSE;
02643
02644 LOG ("measuring mirror : " << i << nl);
02645
02646 m_vMirrs [i].dwPingTime = pinger.Ping (m_vMirrs [i].dnp.pszServerName);
02647
02648 LOG ("measured." << nl);
02649 }
02650
02651 return TRUE;
02652 }
02653
02654 int fsInternetDownloader::GetMirrorRefs(int iMirrorIndex)
02655 {
02656 int cRefs = 0;
02657 for (int i = 0; i < m_vSections.size (); i++)
02658 if (m_vSections [i].nMirrorURL == UINT (iMirrorIndex))
02659 cRefs ++;
02660
02661 return cRefs;
02662 }
02663
02664 BOOL fsInternetDownloader::IsSectionCreatingNow()
02665 {
02666 if (GetCreatingNowSectionCount (UINT_MAX))
02667 return TRUE;
02668
02669 for (int i = 0; i < m_vMirrs.size (); i++)
02670 {
02671 if (GetCreatingNowSectionCount (i))
02672 return TRUE;
02673 }
02674
02675 return FALSE;
02676 }
02677
02678 void fsInternetDownloader::Set_MirrFileMinSize(UINT u)
02679 {
02680 m_uMirrFileMinSize = u;
02681 }
02682
02683 void fsInternetDownloader::Set_MirrCalcSpeed(BOOL b)
02684 {
02685 m_bMirrMeasureSpeed = b;
02686 }
02687
02688 void fsInternetDownloader::Set_MirrMaxCount(UINT u)
02689 {
02690 m_cMaxMirrs = u;
02691 }
02692
02693 void fsInternetDownloader::Set_MirrDontSearchIfSizeUnk(BOOL b)
02694 {
02695 m_bMirrDontSearchIfSizeUnk = b;
02696 }
02697
02698 fsInternetResult fsInternetDownloader::Auto_SearchMirrors()
02699 {
02700 if (m_bSearchForMirrors == FALSE)
02701 return IR_S_FALSE;
02702
02703 if (m_bMirrDontSearchIfSizeUnk && m_uSSFileSize == _UI64_MAX)
02704 return IR_S_FALSE;
02705
02706 if (m_uLDFileSize < m_uMirrFileMinSize || m_uLDFileSize < 100*1024)
02707 return IR_S_FALSE;
02708
02709 return FindMirrors ();
02710 }
02711
02712 DWORD fsInternetDownloader::GetMirrorPingTime(int iMirr)
02713 {
02714 return m_vMirrs [iMirr].dwPingTime;
02715 }
02716
02717 BOOL fsInternetDownloader::GetMirrorIsGood(int iMirr)
02718 {
02719 return m_vMirrs [iMirr].bIsGood;
02720 }
02721
02722 void fsInternetDownloader::RemoveAllMirrors()
02723 {
02724 for (int i = 0; i < m_vMirrs.size (); i++)
02725 fsDNP_GetByUrl_Free (&m_vMirrs [i].dnp);
02726
02727 m_vMirrs.clear ();
02728 m_dwState &= ~ IDS_MIRRSEARCHPERFORMED;
02729 m_strFileName = "";
02730 }
02731
02732 void fsInternetDownloader::AddMirror(fsDownload_NetworkProperties *dnp, BOOL bIsGood, BOOL bDontMeasureSpeed)
02733 {
02734 fsMirrorURLInfo mirr;
02735
02736 if (m_bMirrMeasureSpeed && bDontMeasureSpeed == FALSE)
02737 {
02738 fsSitePingMgr pinger;
02739 if (pinger.TestState ())
02740 mirr.dwPingTime = pinger.Ping (dnp->pszServerName);
02741 }
02742
02743 mirr.dnp = *dnp;
02744 mirr.bIsGood = bIsGood;
02745
02746 LOG ("adding mirror...");
02747
02748 m_vMirrs.add (mirr);
02749
02750 LOG ("ok." << nl);
02751 }
02752
02753 DWORD fsInternetDownloader::Get_BaseServerPingTime()
02754 {
02755 return m_dwBaseServerPingTime;
02756 }
02757
02758 void fsInternetDownloader::Set_BaseServerPingTime(DWORD dw)
02759 {
02760 m_dwBaseServerPingTime = dw;
02761 }
02762
02763 BOOL fsInternetDownloader::IsMirrSearchPerformed()
02764 {
02765 return m_dwState & IDS_MIRRSEARCHPERFORMED;
02766 }
02767
02768 void fsInternetDownloader::Set_MirrPingTime(int iMirr, DWORD dw)
02769 {
02770 m_vMirrs [iMirr].dwPingTime = dw;
02771 }
02772
02773 LPCSTR fsInternetDownloader::GetContentType()
02774 {
02775 return m_strContentType;
02776 }
02777
02778 int fsInternetDownloader::GetFoundMirrorCount()
02779 {
02780 return m_cMirrsFound;
02781 }
02782
02783 UINT64 fsInternetDownloader::GetDownloadedBytesCount()
02784 {
02785 UINT64 size = GetLDFileSize ();
02786 if (size != _UI64_MAX)
02787 return size - GetBytesLeft ();
02788
02789 return m_vSections.size () ? m_vSections [0].uDCurrent + m_dwDataLenInCache : 0;
02790 }
02791
02792 LPCSTR fsInternetDownloader::Get_FileName()
02793 {
02794 return m_strFileName;
02795 }
02796
02797 BOOL fsInternetDownloader::RestoreSectionsState_v5(LPBYTE pBuffer, DWORD )
02798 {
02799 if (pBuffer == NULL || m_vSections.size ())
02800 return FALSE;
02801
02802 int cSects = *((LPINT) pBuffer);
02803 fsSection_v3 *pSects = (fsSection_v3*) (pBuffer + sizeof (int));
02804
02805 for (int i = 0; i < cSects; i++)
02806 {
02807 fsSection section;
02808 section = *pSects++;
02809
02810 m_vSections.add (section);
02811
02812 fsSection *sect = &m_vSections [i];
02813
02814 sect->file = NULL;
02815 if (sect->state != SS_DONE)
02816 sect->state = SS_STOPPED;
02817
02818 sect->pThis = this;
02819 sect->uSpeed = 0;
02820 }
02821
02822 pBuffer = LPBYTE (pSects);
02823 int iStrLen = *((LPINT) pBuffer);
02824 pBuffer += sizeof (int);
02825
02826 if (iStrLen > MY_MAX_PATH || iStrLen < 0)
02827 return FALSE;
02828
02829 char sz [10000];
02830 strncpy (sz, LPCSTR (pBuffer), iStrLen);
02831 sz [iStrLen] = 0;
02832 m_strFileName = sz;
02833 pBuffer += iStrLen;
02834
02835 m_dwState = *((LPDWORD) pBuffer);
02836 pBuffer += sizeof (DWORD);
02837
02838 m_uSSFileSize = 0;
02839 while (cSects--)
02840 m_uSSFileSize = max (m_uSSFileSize, m_vSections [cSects].uEnd);
02841 m_uLDFileSize = m_uSSFileSize;
02842
02843 return TRUE;
02844 }
02845
02846 fsInternetResult fsInternetDownloader::CheckIsZIP(UINT64 uStartPosition, fsInternetURLFile **ppFileToCloseIfNeed)
02847 {
02848 if (FALSE == IsMayZIP (uStartPosition ? TRUE : FALSE))
02849 return IR_S_FALSE;
02850
02851 if ((m_dwState & IDS_ZIPPREVIEWALLOWED) == 0 &&
02852 FALSE == Event (DE_CONFIRMARCHIVEDETECTION))
02853 {
02854 m_dwState |= IDS_ZIPPREVIEWPERFORMED;
02855 return IR_S_FALSE;
02856 }
02857
02858 SAFE_DELETE (*ppFileToCloseIfNeed);
02859 m_dwState |= IDS_ZIPPREVIEWALLOWED;
02860
02861 fsArchiveInternetStream file;
02862 fsZipArchiveFastRebuilder zip;
02863 zip.SetSFXSize ((DWORD)uStartPosition);
02864 zip.SetFileSize ((DWORD)m_uSSFileSize);
02865
02866 m_pZipPreviewStream = &file;
02867
02868 fsInternetResult ir;
02869
02870 Event (DE_ZIPPREVIEWSTARTED, int ((fsArchiveRebuilder*)&zip));
02871
02872 file.Set_MaxRetriesCount (m_uMaxAttempts);
02873 ir = file.Open (this, uStartPosition);
02874 if (ir != IR_SUCCESS)
02875 {
02876 m_pZipPreviewStream = NULL;
02877
02878 m_dwState &= ~IDS_ZIPPREVIEWALLOWED;
02879 Event (DE_ZIPPREVIEWFAILED);
02880 return ir;
02881 }
02882
02883 DWORD dwRes = zip.OpenArchive (m_pZipPreviewStream);
02884 if (dwRes != NOERROR)
02885 {
02886 m_pZipPreviewStream = NULL;
02887 Event (DE_ZIPPREVIEWFAILED);
02888
02889 if (dwRes == ARR_STREAMERROR)
02890 return file.GetLastNetworkErr ();
02891
02892 return IR_S_FALSE;
02893 }
02894
02895 file.Close ();
02896 m_pZipPreviewStream = NULL;
02897
02898 if (FALSE == Event (DE_ARCHIVEDETECTED, int ((fsArchiveRebuilder*)&zip)))
02899 {
02900 m_dwState &= ~IDS_ZIPPREVIEWALLOWED;
02901 return (fsInternetResult) 0x1000;
02902 }
02903
02904 m_dwState |= IDS_ZIPPREVIEWPERFORMED;
02905
02906 if (FALSE == Event (DE_NEEDFILE))
02907 return IR_S_FALSE;
02908
02909 fsArchiveFileStream outfile;
02910 outfile.Attach (m_hOutFile);
02911 outfile.Seek (uStartPosition, ST_BEGIN);
02912
02913 zip.SaveArchiveHeaders (&outfile);
02914
02915 outfile.Detach ();
02916
02917 ApplyArchiveRebuilding (&zip, uStartPosition);
02918
02919 return IR_SUCCESS;
02920 }
02921
02922 void fsInternetDownloader::UseZipPreview(BOOL b)
02923 {
02924 if (b)
02925 m_dwState |= IDS_USEZIPPREVIEW;
02926 else
02927 m_dwState &= ~IDS_USEZIPPREVIEW;
02928 }
02929
02930 void fsInternetDownloader::ApplyArchiveRebuilding(fsArchiveRebuilder *ar, UINT64 uAddOffset)
02931 {
02932 m_vSections.clear ();
02933
02934 for (int i = 0; i < ar->GetFileCount (); i++)
02935 {
02936 const fsArchiveFilePosition* filepos = ar->GetFilePosition (i);
02937
02938 fsSection sect;
02939 sect.file = NULL;
02940 sect.iSection = i;
02941 sect.lastErr = IR_SUCCESS;
02942 sect.nMirrorURL = UINT_MAX;
02943 sect.pThis = this;
02944 sect.state = SS_STOPPED;
02945
02946 sect.uStart = sect.uCurrent = filepos->dwSrcBegin + uAddOffset;
02947 sect.uEnd = filepos->dwSrcEnd + uAddOffset;
02948
02949 sect.uDStart = sect.uDCurrent = filepos->dwDstBegin + uAddOffset;
02950 sect.uDEnd = filepos->dwDstEnd + uAddOffset;
02951
02952 TSECT (§);
02953
02954 if (filepos->dwSrcBegin == 0)
02955 sect.uDStart = sect.uStart = 0;
02956
02957
02958 m_vSections.add (sect);
02959 }
02960
02961 for (i = 1; i < m_vSections.size (); i++)
02962 {
02963 fsSection* prev = &m_vSections [i-1];
02964 fsSection* cur = &m_vSections [i];
02965
02966 if (prev->uEnd == cur->uStart)
02967 {
02968
02969 prev->uEnd = cur->uEnd;
02970 prev->uDEnd = cur->uDEnd;
02971
02972 m_vSections.del (i);
02973
02974 for (int j = i; j < m_vSections.size (); j++)
02975 m_vSections [j].iSection--;
02976
02977 i--;
02978 }
02979 }
02980
02981 UINT64 uMaxPos = m_vSections [m_vSections.size ()-1].uEnd;
02982 UINT64 uDMaxPos = m_vSections [m_vSections.size ()-1].uDEnd;
02983
02984 fsSection sect;
02985 sect.file = NULL;
02986 sect.iSection = m_vSections.size ();
02987 sect.lastErr = IR_SUCCESS;
02988 sect.nMirrorURL = UINT_MAX;
02989 sect.pThis = this;
02990 sect.state = SS_DONE;
02991
02992 sect.uStart = uMaxPos;
02993 sect.uEnd = sect.uCurrent = uMaxPos;
02994
02995 m_uLDFileSize = ar->GetResultingArchiveSize () + uAddOffset;
02996
02997 sect.uDStart = uDMaxPos;
02998 sect.uDEnd = sect.uDCurrent = GetLDFileSize ();
02999
03000 TSECT (§);
03001
03002 m_vSections.add (sect);
03003 }
03004
03005 DWORD fsInternetDownloader::GetState()
03006 {
03007 return m_dwState;
03008 }
03009
03010 UINT64 fsInternetDownloader::GetLDFileSize()
03011 {
03012 return m_uLDFileSize;
03013 }
03014
03015 BOOL fsInternetDownloader::IsMayZIP(BOOL bIsExeMay)
03016 {
03017 bIsExeMay = FALSE;
03018
03019 if ((m_dwState & IDS_USEZIPPREVIEW) == 0)
03020 return FALSE;
03021
03022 if (m_dwState & IDS_ZIPPREVIEWPERFORMED)
03023 return FALSE;
03024
03025 if (GetSSFileSize () == _UI64_MAX)
03026 return FALSE;
03027
03028 LPCSTR pszExt = strrchr (m_strFileName, '.');
03029 if (pszExt++ == NULL)
03030 return FALSE;
03031
03032 if (stricmp (pszExt, "zip") == 0)
03033 return TRUE;
03034
03035 if (bIsExeMay && stricmp (pszExt, "exe") == 0)
03036 return TRUE;
03037
03038 return FALSE;
03039 }
03040
03041 void fsInternetDownloader::ApplyProxySettings(fsInternetSession *pSession, fsDownload_NetworkProperties* dnp)
03042 {
03043 pSession->SetProxyAuth (dnp->pszProxyUserName, dnp->pszProxyPassword);
03044 pSession->SetTimeout (m_uTimeout);
03045 }
03046
03047 void fsInternetDownloader::Set_Timeout(UINT u)
03048 {
03049 m_uTimeout = u;
03050 }
03051
03052 BOOL fsInternetDownloader::RemoveMirror(int iIndex)
03053 {
03054 if (m_bAddingSection || m_cBaseSectCreatingNow || m_csOpenUrl.OwningThread != NULL ||
03055 m_vMirrs [iIndex].cSectsCreatingNow)
03056 return FALSE;
03057
03058 EnterCriticalSection (&m_csOpenUrl);
03059
03060
03061 for (int i = 0; i < m_vSections.size (); i++)
03062 {
03063 if (m_vSections [i].nMirrorURL == (UINT)iIndex)
03064 {
03065 m_vSections [i].nMirrorURL = UINT_MAX;
03066 if (m_vSections [i].state == SS_DOWNLOADING)
03067 m_vSections [i].state = SS_NEEDSTOP;
03068 }
03069 else if (m_vSections [i].nMirrorURL != UINT_MAX &&
03070 m_vSections [i].nMirrorURL > (UINT)iIndex)
03071 {
03072 m_vSections [i].nMirrorURL--;
03073 }
03074 }
03075
03076 fsDNP_GetByUrl_Free (&m_vMirrs [iIndex].dnp);
03077 m_vMirrs.del (iIndex);
03078
03079 LeaveCriticalSection (&m_csOpenUrl);
03080 return TRUE;
03081 }
03082
03083 fsString fsInternetDownloader::get_URL(BOOL bIncludeAuthInfo)
03084 {
03085 fsURL url;
03086 char szUrl [10000];
03087 DWORD dw = sizeof (szUrl);
03088
03089 if (IR_SUCCESS != url.Create (fsNPToScheme (DNP ()->enProtocol), DNP ()->pszServerName, DNP ()->uServerPort,
03090 bIncludeAuthInfo ? DNP ()->pszUserName : "", bIncludeAuthInfo ? DNP ()->pszPassword : "",
03091 DNP ()->pszPathName, szUrl, &dw))
03092 {
03093 return "";
03094 }
03095
03096 return szUrl;
03097 }
03098
03099 FILETIME fsInternetDownloader::get_FileDate()
03100 {
03101 return m_fileDate;
03102 }
03103
03104 BOOL fsInternetDownloader::is_WasAccessedAtLeastOnce()
03105 {
03106 return m_bWasAccessedAtLeastOnce;
03107 }
03108
03109 void fsInternetDownloader::set_PauseMode(BOOL bPause)
03110 {
03111 m_bPauseMode = bPause;
03112 }
03113
03114 BOOL fsInternetDownloader::is_PauseMode()
03115 {
03116 return m_bPauseMode;
03117 }
03118
03119 void fsInternetDownloader::OnDataDownloaded(UINT64 nDataSize)
03120 {
03121 m_csDataRcvd.Lock ();
03122 m_nTotalTraffic += nDataSize;
03123 m_TotalSpeed.Done ((DWORD)nDataSize);
03124 m_csDataRcvd.Unlock ();
03125 }
03126
03127 UINT64 fsInternetDownloader::get_TotalTraffic()
03128 {
03129 return m_nTotalTraffic;
03130 }
03131
03132 UINT64 fsInternetDownloader::get_TotalSpeed()
03133 {
03134 return m_TotalSpeed.GetSpeed ();
03135 }
03136
03137 void fsInternetDownloader::ResetTotalTrafficInfo()
03138 {
03139 m_csDataRcvd.Lock ();
03140 m_nTotalTraffic = 0;
03141 m_csDataRcvd.Unlock ();
03142 }
03143
03144 BOOL fsInternetDownloader::IsCompletelyStopped ()
03145 {
03146 return m_cThreads != 0;
03147 }
03148
03149 DWORD WINAPI fsInternetDownloader::_threadOpenUrl(LPVOID lp)
03150 {
03151 _inc_tOU_param *p = (_inc_tOU_param*) lp;
03152
03153 DWORD dw = p->pFile->Open (fsNPToScheme (p->dnp->enProtocol), p->dnp->pszServerName,
03154 p->dnp->pszUserName, p->dnp->pszPassword, p->dnp->uServerPort,
03155 p->dnp->pszPathName, p->uStartPos, p->dnp->dwFlags & DNPF_IMMEDIATELY_SEND_AUTH_AS_BASIC);
03156
03157 delete p;
03158
03159 return dw;
03160 }
03161
03162 void fsInternetDownloader::LockWriteFile(BOOL bLock)
03163 {
03164 if (bLock)
03165 EnterCriticalSection (&m_csWriteToFile);
03166 else
03167 LeaveCriticalSection (&m_csWriteToFile);
03168 }