[cpp-sp] branch main updated: SSPCPP-956 - Add "retryErrors" parameter to TCPListener directive

Scott Cantor cantor.2 at osu.edu
Mon Oct 24 13:58:40 UTC 2022


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=54dfebe82cccafcef79f44701cd1bb0fa2698f8c

The following commit(s) were added to refs/heads/main by this push:
     new 54dfebe8 SSPCPP-956 - Add "retryErrors" parameter to TCPListener directive
54dfebe8 is described below

commit 54dfebe82cccafcef79f44701cd1bb0fa2698f8c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Oct 24 09:58:07 2022 -0400

    SSPCPP-956 - Add "retryErrors" parameter to TCPListener directive
    
    https://shibboleth.atlassian.net/browse/SSPCPP-956
---
 schemas/shibboleth-3.0-native-sp-config.xsd |  3 +-
 shibsp/remoting/impl/SocketListener.cpp     | 83 ++++++++++++++++++++++-------
 shibsp/remoting/impl/SocketListener.h       |  5 +-
 shibsp/remoting/impl/TCPListener.cpp        | 12 +++++
 4 files changed, 83 insertions(+), 20 deletions(-)

diff --git a/schemas/shibboleth-3.0-native-sp-config.xsd b/schemas/shibboleth-3.0-native-sp-config.xsd
index f06affa3..9eb7a4bb 100644
--- a/schemas/shibboleth-3.0-native-sp-config.xsd
+++ b/schemas/shibboleth-3.0-native-sp-config.xsd
@@ -9,7 +9,7 @@
 	elementFormDefault="qualified"
 	attributeFormDefault="unqualified"
 	blockDefault="substitution"
-	version="3.2">
+	version="3.4">
 
   <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" />
   <import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>
@@ -877,6 +877,7 @@
               <attribute name="clientPort" type="unsignedInt"/>
               <attribute name="acl" type="conf:listOfStrings"/>
               <attribute name="stackSize" type="unsignedInt"/>
+              <attribute name="retryErrors" type="conf:string"/>
             </complexType>
           </element>
           <element name="Listener" type="conf:PluggableType"/>
diff --git a/shibsp/remoting/impl/SocketListener.cpp b/shibsp/remoting/impl/SocketListener.cpp
index 4c475376..55c5c38a 100644
--- a/shibsp/remoting/impl/SocketListener.cpp
+++ b/shibsp/remoting/impl/SocketListener.cpp
@@ -34,6 +34,9 @@
 #include <stack>
 #include <sstream>
 #include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
 #include <xercesc/sax/SAXException.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xercesc/util/OutOfMemoryException.hpp>
@@ -223,6 +226,16 @@ bool SocketListener::init(bool force)
     return true;
 }
 
+void SocketListener::set_retry_errors(const string& retry_errors)
+{
+    const char* error_list = retry_errors.c_str();
+    std::vector<string> string_list;
+    boost::split(string_list, error_list, boost::is_any_of(", \t"), boost::token_compress_on);
+    for (vector<string>::const_iterator i = string_list.begin(); i != string_list.end(); ++i) {
+        m_retry_errors.push_back(atoi(i->c_str()));
+    }
+}
+
 bool SocketListener::run(bool* shutdown)
 {
 #ifdef _DEBUG
@@ -325,36 +338,68 @@ DDF SocketListener::send(const DDF& in)
         if (send(sock,(char*)&len,sizeof(len)) != sizeof(len) || send(sock,ostr.c_str(),outlen) != outlen) {
             log_error();
             this->close(sock);
-            if (retry)
+            if (retry) {
                 retry--;
+                log->debug("retrying failed send");
+            }
             else
                 throw ListenerException("Failure sending remoted message ($1).", params(1,in.name()));
         }
         else {
             // SUCCESS.
+            log->debug("send completed, reading response message");
+
+            // Read the message size.
+            int size_read;
+            bool retry_error = false;
+            while ((size_read = recv(sock,(char*)&len,sizeof(len))) != sizeof(len)) {
+                // Apparently this happens when a signal interrupts the blocking call.
+                if (errno == EINTR) continue;
+
+                int native_error;
+                if (size_read == -1) {
+                    log_error("reading size of output message", &native_error);
+                }
+                else {
+                    log->error("error reading size of output message (%d != %d)", size_read, sizeof(len));
+                    native_error = 0;
+                }
+                this->close(sock);
+
+                if (std::find(m_retry_errors.begin(), m_retry_errors.end(), native_error) != m_retry_errors.end()) {
+                    log->debug("recv error %d is retryable", native_error);
+                    if (retry) {
+                        retry_error = true;
+                        retry--;
+                        break;
+                    }
+                    else {
+                        log->debug("not retrying on second failure");
+                    }
+                }
+                else {
+                      log->debug("recv error %d is not retryable", native_error);
+                }
+
+                throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
+            }
+
+            // If recv had retryable error restart loop and try again
+            if (retry_error) {
+                log->debug("retrying");
+                retry_error = false;
+                continue;
+            }
+
+            len = ntohl(len);
             retry = -1;
         }
     }
 
-    log->debug("send completed, reading response message");
-
     // Read the message.
-    int size_read;
-    while ((size_read = recv(sock,(char*)&len,sizeof(len))) != sizeof(len)) {
-    	if (errno == EINTR) continue;	// Apparently this happens when a signal interrupts the blocking call.
-	if (size_read == -1) {
-	    log_error("reading size of output message");
-	}
-	else {
-	    log->error("error reading size of output message (%d != %d)", size_read, sizeof(len));
-	}
-        this->close(sock);
-        throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
-    }
-    len = ntohl(len);
-
     char buf[16384];
     stringstream is;
+    int size_read;
     while (len) {
     	size_read = recv(sock, buf, sizeof(buf));
     	if (size_read > 0) {
@@ -400,7 +445,7 @@ DDF SocketListener::send(const DDF& in)
     return out;
 }
 
-bool SocketListener::log_error(const char* fn) const
+bool SocketListener::log_error(const char* fn, int* native_error) const
 {
     if (!fn)
         fn = "unknown";
@@ -413,6 +458,8 @@ bool SocketListener::log_error(const char* fn) const
 #else
     int rc=errno;
 #endif
+    if (native_error != nullptr)
+        *native_error = rc;
     const char *msg;
 #ifdef HAVE_STRERROR_R
     char buf[256];
diff --git a/shibsp/remoting/impl/SocketListener.h b/shibsp/remoting/impl/SocketListener.h
index 5c6e34ba..4a183e68 100644
--- a/shibsp/remoting/impl/SocketListener.h
+++ b/shibsp/remoting/impl/SocketListener.h
@@ -79,13 +79,16 @@ namespace shibsp {
 
         bool m_catchAll;
     protected:
-        bool log_error(const char* fn=nullptr) const; // for OS-level errors
+        void set_retry_errors(const std::string& retry_errors);
+        bool log_error(const char* fn=nullptr, int* native_error=nullptr) const; // for OS-level errors
         xmltooling::logging::Category* log;
         /// @endcond
 
     private:
+
         boost::scoped_ptr<SocketPool> m_socketpool;
         bool* m_shutdown;
+        std::vector<int> m_retry_errors;
 
         // Manage child threads
         friend class ServerThread;
diff --git a/shibsp/remoting/impl/TCPListener.cpp b/shibsp/remoting/impl/TCPListener.cpp
index 89d61e34..ee437ae9 100644
--- a/shibsp/remoting/impl/TCPListener.cpp
+++ b/shibsp/remoting/impl/TCPListener.cpp
@@ -108,6 +108,7 @@ namespace shibsp {
     static const XMLCh acl[] = UNICODE_LITERAL_3(a,c,l);
     static const XMLCh clientAddress[] = UNICODE_LITERAL_13(c,l,i,e,n,t,A,d,d,r,e,s,s);
     static const XMLCh clientPort[] = UNICODE_LITERAL_10(c,l,i,e,n,t,P,o,r,t);
+    static const XMLCh retryErrors[] = UNICODE_LITERAL_11(r,e,t,r,y,E,r,r,o,r,s);
 };
 
 TCPListener::TCPListener(const DOMElement* e) : SocketListener(e), m_port(0)
@@ -116,6 +117,17 @@ TCPListener::TCPListener(const DOMElement* e) : SocketListener(e), m_port(0)
     if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
         m_address = XMLHelper::getAttrString(e, nullptr, clientAddress);
         m_port = XMLHelper::getAttrInt(e, 0, clientPort);
+        string retry_errors = XMLHelper::getAttrString(e, nullptr, retryErrors);
+        if (!retry_errors.empty()) {
+            if (retry_errors.find_first_not_of("0123456789, \t") == std::string::npos) {
+                log->info("retrying on error codes: %s", retry_errors.c_str());
+                set_retry_errors(retry_errors);
+            }
+            else {
+                log->error("invalid characters in retryErrors, skipping");
+            }
+
+        }
     }
 
     // Back-off to address setting, environment, or default.

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list