summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
Diffstat (limited to 'methods')
-rw-r--r--methods/http.cc86
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";