summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2017-06-28 13:20:54 +0200
committerJulian Andres Klode <jak@debian.org>2017-06-28 15:52:38 +0200
commitf806530b9ea858ca6bda8fb8f43d988aba02dab3 (patch)
tree23d237b5912c43ff6926c7d7d8e2f134cc90f4b4
parent0fe2161020d6e331639ed11872a947dd20035890 (diff)
methods: http: Drain pending data before selecting
GnuTLS can already have data pending in its buffers, we need to to drain that first otherwise select() might block indefinitely. Gbp-Dch: ignore
-rw-r--r--methods/connect.cc9
-rw-r--r--methods/connect.h2
-rw-r--r--methods/http.cc10
3 files changed, 20 insertions, 1 deletions
diff --git a/methods/connect.cc b/methods/connect.cc
index c40f34f2d..e48008214 100644
--- a/methods/connect.cc
+++ b/methods/connect.cc
@@ -98,6 +98,10 @@ struct FdFd : public MethodFd
}
};
+bool MethodFd::HasPending()
+{
+ return false;
+}
std::unique_ptr<MethodFd> MethodFd::FromFd(int iFd)
{
FdFd *fd = new FdFd();
@@ -626,6 +630,11 @@ struct TlsFd : public MethodFd
return -1;
return UnderlyingFd->Close();
}
+
+ bool HasPending() APT_OVERRIDE
+ {
+ return gnutls_record_check_pending(session) > 0;
+ }
};
bool UnwrapTLS(std::string Host, std::unique_ptr<MethodFd> &Fd,
diff --git a/methods/connect.h b/methods/connect.h
index 39f3c1ce2..4456d660d 100644
--- a/methods/connect.h
+++ b/methods/connect.h
@@ -35,6 +35,8 @@ struct MethodFd
virtual ~MethodFd(){};
/// \brief Construct a MethodFd from a UNIX file descriptor
static std::unique_ptr<MethodFd> FromFd(int iFd);
+ /// \brief If there is pending data.
+ virtual bool HasPending();
};
bool Connect(std::string To, int Port, const char *Service, int DefPort,
diff --git a/methods/http.cc b/methods/http.cc
index 4d8c0808b..b302c896d 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -621,7 +621,15 @@ bool HttpServerState::Go(bool ToFile, RequestState &Req)
if (ServerFd->Fd() == -1 && (In.WriteSpace() == false ||
ToFile == false))
return false;
-
+
+ // Handle server IO
+ if (ServerFd->HasPending() && In.ReadSpace() == true)
+ {
+ errno = 0;
+ if (In.Read(ServerFd) == false)
+ return Die(Req);
+ }
+
fd_set rfds,wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);