refactor the interpretation of SSL errors into a function
authorWoo Xie <woo@fb.com>
Thu, 11 Jun 2015 20:25:03 +0000 (13:25 -0700)
committerSara Golemon <sgolemon@fb.com>
Thu, 11 Jun 2015 21:49:22 +0000 (14:49 -0700)
Summary: This fucntion will be re-used for different SSL write functions in future.

Reviewed By: @djwatson

Differential Revision: D2117529

folly/io/async/AsyncSSLSocket.cpp
folly/io/async/AsyncSSLSocket.h

index 0489b6a4991de57f1d14c121079604a8f59885ff..447f2543c02e316e2952943a9c22027b74552a07 100644 (file)
@@ -1181,6 +1181,44 @@ void AsyncSSLSocket::handleWrite() noexcept {
   AsyncSocket::handleWrite();
 }
 
+int AsyncSSLSocket::interpretSSLError(int rc, int error) {
+  if (error == SSL_ERROR_WANT_READ) {
+    // TODO: Even though we are attempting to write data, SSL_write() may
+    // need to read data if renegotiation is being performed.  We currently
+    // don't support this and just fail the write.
+    LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
+               << ", sslState=" << sslState_ << ", events=" << eventFlags_
+               << "): " << "unsupported SSL renegotiation during write",
+      errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_WRITE,
+                       SSL_INVALID_RENEGOTIATION);
+    ERR_clear_error();
+    return -1;
+  } else {
+    // TODO: Fix this code so that it can return a proper error message
+    // to the callback, rather than relying on AsyncSocket code which
+    // can't handle SSL errors.
+    long lastError = ERR_get_error();
+    VLOG(3) << "ERROR: AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
+            << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
+            << "SSL error: " << error << ", errno: " << errno
+            << ", func: " << ERR_func_error_string(lastError)
+            << ", reason: " << ERR_reason_error_string(lastError);
+    if (error != SSL_ERROR_SYSCALL) {
+      if ((unsigned long)lastError < 0x8000) {
+        errno = ENOSYS;
+      } else {
+        errno = lastError;
+      }
+    }
+    ERR_clear_error();
+    if (!zero_return(error, rc)) {
+      return -1;
+    } else {
+      return 0;
+    }
+  }
+}
+
 ssize_t AsyncSSLSocket::performWrite(const iovec* vec,
                                       uint32_t count,
                                       WriteFlags flags,
@@ -1192,7 +1230,8 @@ ssize_t AsyncSSLSocket::performWrite(const iovec* vec,
   }
   if (sslState_ != STATE_ESTABLISHED) {
     LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
-               << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
+               << ", sslState=" << sslState_
+               << ", events=" << eventFlags_ << "): "
                << "TODO: AsyncSSLSocket currently does not support calling "
                << "write() before the handshake has fully completed";
       errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_WRITE,
@@ -1286,40 +1325,11 @@ ssize_t AsyncSSLSocket::performWrite(const iovec* vec,
         // The caller will register for write event if not already.
         *partialWritten = offset;
         return totalWritten;
-      } else if (error == SSL_ERROR_WANT_READ) {
-        // TODO: Even though we are attempting to write data, SSL_write() may
-        // need to read data if renegotiation is being performed.  We currently
-        // don't support this and just fail the write.
-        LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
-                   << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
-                   << "unsupported SSL renegotiation during write",
-        errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_WRITE,
-                         SSL_INVALID_RENEGOTIATION);
-        ERR_clear_error();
-        return -1;
-      } else {
-        // TODO: Fix this code so that it can return a proper error message
-        // to the callback, rather than relying on AsyncSocket code which
-        // can't handle SSL errors.
-        long lastError = ERR_get_error();
-        VLOG(3) <<
-          "ERROR: AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
-                << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
-                << "SSL error: " << error << ", errno: " << errno
-                << ", func: " << ERR_func_error_string(lastError)
-                << ", reason: " << ERR_reason_error_string(lastError);
-        if (error != SSL_ERROR_SYSCALL) {
-          if ((unsigned long)lastError < 0x8000) {
-            errno = ENOSYS;
-          } else {
-            errno = lastError;
-          }
-        }
-        ERR_clear_error();
-        if (!zero_return(error, bytes)) {
-          return -1;
-        } // else fall through to below to correctly record totalWritten
       }
+      int rc = interpretSSLError(bytes, error);
+      if (rc < 0) {
+        return rc;
+      } // else fall through to below to correctly record totalWritten
     }
 
     totalWritten += bytes;
index 393b87650defdc9a6f636f86dba4daaf9e130565..b72205de8a8ecd52d2140ed11415760bbac2563f 100644 (file)
@@ -686,6 +686,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
   // AsyncSocket calls this at the wrong time for SSL
   void handleInitialReadWrite() noexcept override {}
 
+  int interpretSSLError(int rc, int error);
   ssize_t performRead(void* buf, size_t buflen) override;
   ssize_t performWrite(const iovec* vec, uint32_t count, WriteFlags flags,
                        uint32_t* countWritten, uint32_t* partialWritten)