diff options
Diffstat (limited to 'methods/http.cc')
-rw-r--r-- | methods/http.cc | 86 |
1 files changed, 39 insertions, 47 deletions
diff --git a/methods/http.cc b/methods/http.cc index 71aa56751..9cfc91330 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -23,6 +23,7 @@ #include <apt-pkg/fileutl.h> #include <apt-pkg/hashes.h> #include <apt-pkg/proxy.h> +#include <apt-pkg/string_view.h> #include <apt-pkg/strutl.h> #include <chrono> @@ -93,6 +94,7 @@ void CircleBuf::Reset() is non-blocking.. */ bool CircleBuf::Read(std::unique_ptr<MethodFd> const &Fd) { + size_t ReadThisCycle = 0; while (1) { // Woops, buffer is full @@ -130,7 +132,7 @@ bool CircleBuf::Read(std::unique_ptr<MethodFd> const &Fd) CircleBuf::BwTickReadData += Res; if (Res == 0) - return false; + return ReadThisCycle != 0; if (Res < 0) { if (errno == EAGAIN) @@ -139,6 +141,7 @@ bool CircleBuf::Read(std::unique_ptr<MethodFd> const &Fd) } InP += Res; + ReadThisCycle += Res; } } /*}}}*/ @@ -203,8 +206,6 @@ bool CircleBuf::Write(std::unique_ptr<MethodFd> const &Fd) ssize_t Res; Res = Fd->Write(Buf + (OutP % Size), LeftWrite()); - if (Res == 0) - return false; if (Res < 0) { if (errno == EAGAIN) @@ -214,7 +215,7 @@ bool CircleBuf::Write(std::unique_ptr<MethodFd> const &Fd) } TotalWriten += Res; - + if (Hash != NULL) Hash->Add(Buf + (OutP%Size),Res); @@ -407,7 +408,7 @@ static ResultState UnwrapHTTPConnect(std::string Host, int Port, URI Proxy, std: /*}}}*/ // HttpServerState::HttpServerState - Constructor /*{{{*/ -HttpServerState::HttpServerState(URI Srv,HttpMethod *Owner) : ServerState(Srv, Owner), In(Owner, 64*1024), Out(Owner, 4*1024) +HttpServerState::HttpServerState(URI Srv, HttpMethod *Owner) : ServerState(Srv, Owner), In(Owner, APT_BUFFER_SIZE), Out(Owner, 4 * 1024) { TimeOut = Owner->ConfigFindI("Timeout", TimeOut); ServerFd = MethodFd::FromFd(-1); @@ -699,26 +700,18 @@ ResultState HttpServerState::Die(RequestState &Req) { unsigned int LErrno = errno; + Close(); + // Dump the buffer to the file if (Req.State == RequestState::Data) { - if (Req.File.IsOpen() == false) - return ResultState::SUCCESSFUL; // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking // can't be set if (Req.File.Name() != "/dev/null") SetNonBlock(Req.File.Fd(),false); - while (In.WriteSpace() == true) - { - if (In.Write(MethodFd::FromFd(Req.File.Fd())) == false) - { - _error->Errno("write", _("Error writing to the file")); - return ResultState::TRANSIENT_ERROR; - } - - // Done - if (In.IsLimit() == true) - return ResultState::SUCCESSFUL; + if (In.WriteSpace()) { + _error->Error(_("Data left in buffer")); + return ResultState::TRANSIENT_ERROR; } } @@ -726,7 +719,6 @@ ResultState HttpServerState::Die(RequestState &Req) if (In.IsLimit() == false && Req.State != RequestState::Header && Persistent == true) { - Close(); if (LErrno == 0) { _error->Error(_("Error reading from server. Remote end closed connection")); @@ -745,7 +737,6 @@ ResultState HttpServerState::Die(RequestState &Req) return ResultState::TRANSIENT_ERROR; // We may have got multiple responses back in one packet.. - Close(); return ResultState::SUCCESSFUL; } @@ -792,13 +783,11 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) ToFile == false)) return ResultState::TRANSIENT_ERROR; - // Handle server IO - if (ServerFd->HasPending() && In.ReadSpace() == true) - { - errno = 0; - if (In.Read(ServerFd) == false) - return Die(Req); - } + // Record if we have data pending to read in the server, so that we can + // skip the wait in select(). This can happen if data has already been + // read into a methodfd's buffer - the TCP queue might be empty at that + // point. + bool ServerPending = ServerFd->HasPending(); fd_set rfds,wfds; FD_ZERO(&rfds); @@ -830,7 +819,7 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) // Select struct timeval tv; - tv.tv_sec = TimeOut; + tv.tv_sec = ServerPending ? 0 : TimeOut; tv.tv_usec = 0; int Res = 0; if ((Res = select(MaxFd+1,&rfds,&wfds,0,&tv)) < 0) @@ -841,27 +830,20 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) return ResultState::TRANSIENT_ERROR; } - if (Res == 0) + if (Res == 0 && not ServerPending) { _error->Error(_("Connection timed out")); - return Die(Req); + return ResultState::TRANSIENT_ERROR; } // Handle server IO - if (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &rfds)) + if (ServerPending || (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &rfds))) { errno = 0; if (In.Read(ServerFd) == false) return Die(Req); } - if (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &wfds)) - { - errno = 0; - if (Out.Write(ServerFd) == false) - return Die(Req); - } - // Send data to the file if (FileFD->Fd() != -1 && FD_ISSET(FileFD->Fd(), &wfds)) { @@ -872,6 +854,13 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) } } + if (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &wfds)) + { + errno = 0; + if (Out.Write(ServerFd) == false) + return Die(Req); + } + if (Req.MaximumSize > 0 && Req.File.IsOpen() && Req.File.Failed() == false && Req.File.Tell() > Req.MaximumSize) { Owner->SetFailReason("MaximumSizeExceeded"); @@ -979,15 +968,18 @@ void HttpMethod::SendReq(FetchItem *Itm) "Debian APT-HTTP/1.3 (" PACKAGE_VERSION ")"); #ifdef HAVE_SYSTEMD - char *unit = nullptr; - sd_pid_get_unit(getpid(), &unit); - if (unit != nullptr && *unit != '\0' && not APT::String::Startswith(unit, "user@") // user@ _is_ interactive - && unit != "packagekit.service"s // packagekit likely is interactive - && unit != "dbus.service"s // aptdaemon and qapt don't have systemd services - && ConfigFindB("User-Agent-Non-Interactive", false)) - Req << " non-interactive"; - - free(unit); + if (ConfigFindB("User-Agent-Non-Interactive", false)) + { + using APT::operator""_sv; + char *unit = nullptr; + sd_pid_get_unit(getpid(), &unit); + if (unit != nullptr && *unit != '\0' && not APT::String::Startswith(unit, "user@") // user@ _is_ interactive + && "packagekit.service"_sv != unit // packagekit likely is interactive + && "dbus.service"_sv != unit) // aptdaemon and qapt don't have systemd services + Req << " non-interactive"; + + free(unit); + } #endif Req << "\r\n"; |