title: SSL shutdown with check for error code and consideration of pending data
body: <p>I would like to ensure a proper shutdown of an SSL connection. From <a href="https://stackoverflow.com/q/22575315/1460794">this question</a> I found a code snippet to distinguish a graceful shutdown from a short read error:</p>
  
  <pre><code>// const boost::system::error_code &amp;ec
  if (ec.category() == asio::error::get_ssl_category() &amp;&amp;
    ec.value() == ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ)) {
    // -&gt; not a real error, just a normal TLS shutdown
  }
  </code></pre>
  
  <p>The code above makes sense in light of the following code in <a href="http://www.boost.org/doc/libs/1_61_0/boost/asio/ssl/detail/impl/engine.ipp" rel="nofollow noreferrer"><code>engine.ipp</code></a>:</p>
  
  <pre><code>const boost::system::error_code&amp; engine::map_error_code(
      boost::system::error_code&amp; ec) const
  {
    // We only want to map the error::eof code.
    if (ec != boost::asio::error::eof)
      return ec;
  
    // If there's data yet to be read, it's an error.
    if (BIO_wpending(ext_bio_))
    {
      ec = boost::system::error_code(
          ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ),
          boost::asio::error::get_ssl_category());
      return ec;
    }
  
    // SSL v2 doesn't provide a protocol-level shutdown, so an eof on the
    // underlying transport is passed through.
    if (ssl_-&gt;version == SSL2_VERSION)
      return ec;
  
    // Otherwise, the peer should have negotiated a proper shutdown.
    if ((::SSL_get_shutdown(ssl_) &amp; SSL_RECEIVED_SHUTDOWN) == 0)
    {
      ec = boost::system::error_code(
          ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ),
          boost::asio::error::get_ssl_category());
    }
  
    return ec;
  }
  </code></pre>
  
  <p>In the code above the error is remapped, which I then check for specifically. But after reading the function above I don't feel reassured. </p>
  
  <p>It seems that both: </p>
  
  <ul>
  <li><code>if (BIO_wpending(ext_bio_))</code> (data to be read), and </li>
  <li><code>if ((::SSL_get_shutdown(ssl_) &amp; SSL_RECEIVED_SHUTDOWN) == 0)</code> (negotiated proper shutdown)</li>
  </ul>
  
  <p>will generate the same error that I'm checking for.</p>
  
  <p>Will my error check miss an error if <code>(BIO_wpending(ext_bio_))</code> is true? I don't know what exactly this check is looking at. Does it matter?</p>