X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/ce1f3a2c616b86da657c1c796efa5f4d18c30c39..a9e4fd6534a2ae6a5a983df77e5b1efa32f3a756:/methods/server.cc diff --git a/methods/server.cc b/methods/server.cc index 650a4aeb8..9db45eb8c 100644 --- a/methods/server.cc +++ b/methods/server.cc @@ -10,7 +10,6 @@ // Include Files /*{{{*/ #include -#include #include #include #include @@ -114,7 +113,7 @@ bool ServerState::HeaderLine(string Line) // Parse off any trailing spaces between the : and the next word. string::size_type Pos2 = Pos; - while (Pos2 < Line.length() && isspace(Line[Pos2]) != 0) + while (Pos2 < Line.length() && isspace_ascii(Line[Pos2]) != 0) Pos2++; string Tag = string(Line,0,Pos); @@ -130,7 +129,7 @@ bool ServerState::HeaderLine(string Line) { Code[0] = '\0'; if (Owner != NULL && Owner->Debug == true) - clog << "HTTP server doesn't give Reason-Phrase for " << Result << std::endl; + clog << "HTTP server doesn't give Reason-Phrase for " << std::to_string(Result) << std::endl; } else if (elements != 4) return _error->Error(_("The HTTP server sent an invalid reply header")); @@ -150,9 +149,15 @@ bool ServerState::HeaderLine(string Line) else { if (Major == 1 && Minor == 0) + { Persistent = false; + } else + { Persistent = true; + if (PipelineAllowed) + Pipeline = true; + } } return true; @@ -240,7 +245,8 @@ bool ServerState::HeaderLine(string Line) } /*}}}*/ // ServerState::ServerState - Constructor /*{{{*/ -ServerState::ServerState(URI Srv, ServerMethod *Owner) : ServerName(Srv), TimeOut(120), Owner(Owner) +ServerState::ServerState(URI Srv, ServerMethod *Owner) : + DownloadSize(0), ServerName(Srv), TimeOut(120), Owner(Owner) { Reset(); } @@ -252,17 +258,6 @@ bool ServerState::AddPartialFileToHashes(FileFd &File) /*{{{*/ } /*}}}*/ -bool ServerMethod::Configuration(string Message) /*{{{*/ -{ - if (pkgAcqMethod::Configuration(Message) == false) - return false; - - DropPrivsOrDie(); - - return true; -} - /*}}}*/ - // ServerMethod::DealWithHeaders - Handle the retrieved header data /*{{{*/ // --------------------------------------------------------------------- /* We look at the header data we got back from the server and decide what @@ -423,36 +418,66 @@ void ServerMethod::SigTerm(int) depth. */ bool ServerMethod::Fetch(FetchItem *) { - if (Server == 0) + if (Server == nullptr || QueueBack == nullptr) return true; - // Queue the requests - int Depth = -1; - for (FetchItem *I = Queue; I != 0 && Depth < (signed)PipelineDepth; - I = I->Next, Depth++) - { - if (Depth >= 0) - { - // If pipelining is disabled, we only queue 1 request - if (Server->Pipeline == false) - break; - // if we have no hashes, do at most one such request - // as we can't fixup pipeling misbehaviors otherwise - else if (I->ExpectedHashes.usable() == false) - break; - } - + // If pipelining is disabled, we only queue 1 request + auto const AllowedDepth = Server->Pipeline ? PipelineDepth : 0; + // how deep is our pipeline currently? + decltype(PipelineDepth) CurrentDepth = 0; + for (FetchItem const *I = Queue; I != QueueBack; I = I->Next) + ++CurrentDepth; + + do { // Make sure we stick with the same server - if (Server->Comp(I->Uri) == false) + if (Server->Comp(QueueBack->Uri) == false) + break; + + bool const UsableHashes = QueueBack->ExpectedHashes.usable(); + // if we have no hashes, do at most one such request + // as we can't fixup pipeling misbehaviors otherwise + if (CurrentDepth != 0 && UsableHashes == false) break; - if (QueueBack == I) + + if (UsableHashes && FileExists(QueueBack->DestFile)) { - QueueBack = I->Next; - SendReq(I); - continue; + FileFd partial(QueueBack->DestFile, FileFd::ReadOnly); + Hashes wehave(QueueBack->ExpectedHashes); + if (QueueBack->ExpectedHashes.FileSize() == partial.FileSize()) + { + if (wehave.AddFD(partial) && + wehave.GetHashStringList() == QueueBack->ExpectedHashes) + { + FetchResult Res; + Res.Filename = QueueBack->DestFile; + Res.ResumePoint = QueueBack->ExpectedHashes.FileSize(); + URIStart(Res); + // move item to the start of the queue as URIDone will + // always dequeued the first item in the queue + if (Queue != QueueBack) + { + FetchItem *Prev = Queue; + for (; Prev->Next != QueueBack; Prev = Prev->Next) + /* look for the previous queue item */; + Prev->Next = QueueBack->Next; + QueueBack->Next = Queue; + Queue = QueueBack; + QueueBack = Prev->Next; + } + Res.TakeHashes(wehave); + URIDone(Res); + continue; + } + else + RemoveFile("Fetch-Partial", QueueBack->DestFile); + } } - } - + auto const Tmp = QueueBack; + QueueBack = QueueBack->Next; + SendReq(Tmp); + ++CurrentDepth; + } while (CurrentDepth <= AllowedDepth && QueueBack != nullptr); + return true; } /*}}}*/ @@ -543,6 +568,7 @@ int ServerMethod::Loop() _error->Discard(); Server->Close(); Server->Pipeline = false; + Server->PipelineAllowed = false; if (FailCounter >= 2) { @@ -615,6 +641,7 @@ int ServerMethod::Loop() strprintf(out, _("Automatically disabled %s due to incorrect response from server/proxy. (man 5 apt.conf)"), "Acquire::http::PipelineDepth"); std::cerr << "W: " << out << std::endl; Server->Pipeline = false; + Server->PipelineAllowed = false; // we keep the PipelineDepth value so that the rest of the queue can be fixed up as well } Rename(Res.Filename, I->DestFile); @@ -753,8 +780,8 @@ unsigned long long ServerMethod::FindMaximumObjectSizeInQueue() const /*{{{*/ return MaxSizeInQueue; } /*}}}*/ -ServerMethod::ServerMethod(const char *Ver,unsigned long Flags) : /*{{{*/ - pkgAcqMethod(Ver, Flags), Server(nullptr), File(NULL), PipelineDepth(10), +ServerMethod::ServerMethod(char const * const Binary, char const * const Ver,unsigned long const Flags) :/*{{{*/ + aptMethod(Binary, Ver, Flags), Server(nullptr), File(NULL), PipelineDepth(10), AllowRedirect(false), Debug(false) { }