title: C++ What is the best way to shutdown a Boost ASIO SSL socket?
body: <p>I have a client application that uses Boost ASIO SSL sockets.  I am running into connection errors that leave the socket in an unusable state until I restart the app.  To begin, I make a connection request with this code:</p>
  
  <pre><code>void apiClient::connect(boost::asio::ip::tcp::resolver::iterator endpoint_list)
  {
      boost::asio::ip::tcp::resolver::iterator endpoint_iter = endpoint_list;
      boost::asio::ip::tcp::endpoint endpoint = *endpoint_iter;
  
      if (!ssl_socket_-&gt;lowest_layer().is_open()) {
          ssl_socket_-&gt;lowest_layer().async_connect(endpoint,
              boost::bind(&amp;apiClient::handle_connect, this,
              boost::asio::placeholders::error, ++endpoint_iter));
      }
  }
  </code></pre>
  
  <p>Periodically I encounter an error returned to the connection handler, the error in ec.message is [A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond] Error code [10060]</p>
  
  <p>Here is my connection handler:</p>
  
  <pre><code>void apiClient::handle_connect(const boost::system::error_code&amp; ec, 
      boost::asio::ip::tcp::resolver::iterator endpoint_list)
  {
      bool found_error(false);
  
      if (!ec) {
          ssl_socket_-&gt;async_handshake(boost::asio::ssl::stream_base::client,
              boost::bind(&amp;apiClient::send_request, this, 
              boost::asio::placeholders::error));
      }
      else if (endpoint_list != boost::asio::ip::tcp::resolver::iterator()) {
          std::wstring sMsg = boost::str(boost::wformat(L"API server connection failure to host [%s]. Trying next endpoint") % s2ws(endpoint_list-&gt;host_name()));
          LogMsg(sMsg);
          found_error = true;
          epList = endpoint_list;
      }
      else {
          std::wstring sMsg = boost::str(boost::wformat(L"API server connection failure.  Error msg [%s] Error code [%d]") % s2ws(ec.message()) % ec.value());
          LogMsg(sMsg);
          found_error = true;
          epList = start_endpoint_list;
      }
  
      if (found_error) {
          requeue_request(SHUTDOWN_CONN);
      }
  }
  </code></pre>
  
  <p>In my requeue_request function I check the number of errors I have encountered for the request and if it exceeds a threshold, I discard the request and move on.  If I have not exceeded the threshold, I shutdown the socket connection before attempting to reconnect and send the message again.  My understanding is
  that the emplace method recreates the socket instance.</p>
  
  <pre><code>void apiClient::reconnect(SHUTDOWN_CONN_ACTION action)
  {
      if (action == SHUTDOWN_CONN) {
          shutdownSocket();
      }
  
      ssl_socket_.emplace(*io_context_, *ctx_);
  
      connect_timer.expires_from_now(boost::posix_time::milliseconds(3000));
      connect_timer.async_wait(boost::bind(&amp;apiClient::handleConnectTimer, this, boost::asio::placeholders::error));
  }
  
  void CNXGHotKeyAPIClient::shutdownSocket()
  {
      boost::system::error_code ec;
  
      ssl_socket_-&gt;next_layer().cancel(ec);
      ssl_socket_-&gt;shutdown(ec);
      ssl_socket_-&gt;lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
      ssl_socket_-&gt;lowest_layer().close(ec);
  }
  </code></pre>
  
  <p>This design is not working for me.  When I encounter any connection error, my application retries the connection 3 times, it fails with the same error all three times and the socket is left in a state where I cannot use it until I restart my application.  The server I'm connecting to is honoring hundreds of
  connection requests from python apps that do not use Boost so I don't think the server is at fault.</p>
  
  <p>I have tried to find examples that use async_shutdown but I cannot find anything that helps me.  The example at this link <a href="https://stackoverflow.com/questions/32046034/what-is-the-proper-way-to-securely-disconnect-an-asio-ssl-socket">What is the proper way to securely disconnect an asio SSL socket?</a></p>
  
  <p>uses the following code which I am unable to make work.
      example code:</p>
  
  <pre><code>boost::system::error_code ec;
  ssl_socket.cancel(ec);
  ssl_socket.async_shutdown([](...) { ssl_socket.close(); };
  </code></pre>
  
  <p>ssl_socket.cancel() doesn't even exist in my version of Boost (v1.66) the closest thing I can find is ssl_socket.next_layer().cancel(ec)</p>
  
  <p>My question is; how do you shutdown a socket after it has encountered an error so that it is not left in an unusable state?  When my application encounters connection errors, many times I cannot reconnect until I restart the app.  The app is still running and servicing user actions so I know it has not crashed, but the socket is in a state that is unusable.  Thanks for any help</p>