From: James Turner <zakalawe@mac.com>
Date: Tue, 22 Mar 2016 20:06:22 +0000 (+0000)
Subject: Disable HTTP pipelining if the connection closes.
X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=714a6ac47dc87f5d8d873644b8dfff05277726ec;p=simgear.git

Disable HTTP pipelining if the connection closes.

Don’t keep attempting to pipeline if the next server sets Close on
its response, since this just generates needless overhead.
---

diff --git a/simgear/io/HTTPClient.cxx b/simgear/io/HTTPClient.cxx
index 39d03679..d42519d8 100644
--- a/simgear/io/HTTPClient.cxx
+++ b/simgear/io/HTTPClient.cxx
@@ -651,6 +651,11 @@ private:
         activeRequest->responseHeadersComplete();
         _contentDecoder.initWithRequest(activeRequest);
 
+        if (!activeRequest->serverSupportsPipelining()) {
+            SG_LOG(SG_IO, SG_DEBUG, _connectionId << " disabling pipelining since server does not support it");
+            _maxPipelineLength = 1;
+        }
+
         if (chunkedTransfer) {
             setState(STATE_GETTING_CHUNKED);
         } else if (noMessageBody || (bodyTransferSize == 0)) {
diff --git a/simgear/io/HTTPRequest.cxx b/simgear/io/HTTPRequest.cxx
index 3050cbf4..c9d82d29 100644
--- a/simgear/io/HTTPRequest.cxx
+++ b/simgear/io/HTTPRequest.cxx
@@ -39,7 +39,8 @@ Request::Request(const std::string& url, const std::string method):
   _responseLength(0),
   _receivedBodyBytes(0),
   _ready_state(UNSENT),
-  _willClose(false)
+  _willClose(false),
+  _connectionCloseHeader(false)
 {
 
 }
@@ -147,7 +148,10 @@ void Request::responseStart(const std::string& r)
 void Request::responseHeader(const std::string& key, const std::string& value)
 {
   if( key == "connection" ) {
-    _willClose = (value.find("close") != std::string::npos);
+    _connectionCloseHeader = (value.find("close") != std::string::npos);
+      // track willClose seperately because other conditions (abort, for
+      // example) can also set it
+    _willClose = _connectionCloseHeader;
   } else if (key == "content-length") {
     int sz = strutils::to_int(value);
     setResponseLength(sz);
@@ -380,6 +384,12 @@ bool Request::closeAfterComplete() const
   return _willClose || (_responseVersion != HTTP_1_1);
 }
 
+//------------------------------------------------------------------------------
+bool Request::serverSupportsPipelining() const
+{
+    return (_responseVersion == HTTP_1_1) && !_connectionCloseHeader;
+}
+
 //------------------------------------------------------------------------------
 bool Request::isComplete() const
 {
diff --git a/simgear/io/HTTPRequest.hxx b/simgear/io/HTTPRequest.hxx
index 9182ed37..cc7ffd28 100644
--- a/simgear/io/HTTPRequest.hxx
+++ b/simgear/io/HTTPRequest.hxx
@@ -207,6 +207,13 @@ public:
     bool closeAfterComplete() const;
     bool isComplete() const;
 
+    /**
+     * Check if the server response indicates pipelining should be continued.
+     * Currently tests that HTTP_1_1 is explicitly supported, and that the
+     * server/proxy did not request Connection: close
+     */
+    bool serverSupportsPipelining() const;
+
 protected:
     Request(const std::string& url, const std::string method = "GET");
 
@@ -253,6 +260,7 @@ private:
 
     ReadyState    _ready_state;
     bool          _willClose;
+    bool          _connectionCloseHeader;
 };
 
 typedef SGSharedPtr<Request> Request_ptr;