title: Unsolicited messages in boost::asio crashes application, without SSL it works fine, why?
body: <p>I want to send unsolicited messages over an SSL connection. Meaning that the server sends a message not based on a request from a client, but because some event happened that the client needs to know about. </p>
  
  <p>I just use the SSL server example from the boost site, added a timer that sends 'hello' after 10 seconds, everything works fine before the timer expires (the server echo's everything), the 'hello' is also received, but after that the application crashes on the next time a text is sent to the server.</p>
  
  <p>For me even more strange is the fact that when I disable the SSL code, so use a normal socket and do the same using telnet, it works FINE and keeps on working fine!!!</p>
  
  <p>I ran into this problem for the second time now, and I really do not have an idea why this is happening the way it happens.</p>
  
  <p>Below is the total source that I altered to demonstrate the problem. Compile it without the SSL define and use telnet and everything works OK, define SSL and use openssl, or the client  SSL example from the boost website and the thing crashes.</p>
  
  <pre><code>#include &lt;cstdlib&gt;
  #include &lt;iostream&gt;
  #include &lt;boost/bind.hpp&gt;
  #include &lt;boost/asio.hpp&gt;
  #include &lt;boost/asio/ssl.hpp&gt;
  
  //#define SSL
  
  typedef boost::asio::ssl::stream&lt;boost::asio::ip::tcp::socket&gt; ssl_socket;
  
  class session
  {
  public:
    session(boost::asio::io_service&amp; io_service,
        boost::asio::ssl::context&amp; context)
  #ifdef SSL  
      : socket_(io_service, context)
  #else
      : socket_(io_service)
  
  #endif    
    {
    }
  
    ssl_socket::lowest_layer_type&amp; socket()
    {
      return socket_.lowest_layer();
    }
  
    void start()
    {
  #ifdef SSL      
      socket_.async_handshake(boost::asio::ssl::stream_base::server,
          boost::bind(&amp;session::handle_handshake, this,
            boost::asio::placeholders::error));
  #else
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
            boost::bind(&amp;session::handle_read, this,
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
  
        boost::shared_ptr&lt; boost::asio::deadline_timer &gt; timer(new     boost::asio::deadline_timer( socket_.get_io_service() ));
        timer-&gt;expires_from_now( boost::posix_time::seconds( 10 ) );
        timer-&gt;async_wait( boost::bind( &amp;session::SayHello, this, _1, timer ) );
  
  #endif    
    }
  
    void handle_handshake(const boost::system::error_code&amp; error)
    {
      if (!error)
      {
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
            boost::bind(&amp;session::handle_read, this,
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
  
        boost::shared_ptr&lt; boost::asio::deadline_timer &gt; timer(new     boost::asio::deadline_timer( socket_.get_io_service() ));
        timer-&gt;expires_from_now( boost::posix_time::seconds( 10 ) );
        timer-&gt;async_wait( boost::bind( &amp;session::SayHello, this, _1, timer ) );
  
      }
      else
      {
        delete this;
      }
    }
  
    void SayHello(const boost::system::error_code&amp; error, boost::shared_ptr&lt;     boost::asio::deadline_timer &gt; timer) {
        std::string hello = "hello";
  
          boost::asio::async_write(socket_,
            boost::asio::buffer(hello, hello.length()),
            boost::bind(&amp;session::handle_write, this,
              boost::asio::placeholders::error));
  
        timer-&gt;expires_from_now( boost::posix_time::seconds( 10 ) );
        timer-&gt;async_wait( boost::bind( &amp;session::SayHello, this, _1, timer ) );
  
    }
  
  
    void handle_read(const boost::system::error_code&amp; error,
        size_t bytes_transferred)
    {
      if (!error)
      {
        boost::asio::async_write(socket_,
            boost::asio::buffer(data_, bytes_transferred),
            boost::bind(&amp;session::handle_write, this,
              boost::asio::placeholders::error));
      }
      else
      {
        std::cout &lt;&lt; "session::handle_read() -&gt; Delete, ErrorCode: "&lt;&lt; error.value() &lt;&lt;     std::endl;
        delete this;
      }
    }
  
    void handle_write(const boost::system::error_code&amp; error)
    {
      if (!error)
      {
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
            boost::bind(&amp;session::handle_read, this,
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
      }
      else
      {
        std::cout &lt;&lt; "session::handle_write() -&gt; Delete, ErrorCode: "&lt;&lt; error.value() &lt;&lt;     std::endl;
        delete this;
      }
    }
  
  private:
  #ifdef SSL    
    ssl_socket socket_;
  #else
    boost::asio::ip::tcp::socket socket_;
  #endif  
    enum { max_length = 1024 };
    char data_[max_length];
  };
  
  class server
  {
  public:
    server(boost::asio::io_service&amp; io_service, unsigned short port)
      : io_service_(io_service),
        acceptor_(io_service,
            boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
        context_(boost::asio::ssl::context::sslv23)
    {
  #ifdef SSL        
      context_.set_options(
          boost::asio::ssl::context::default_workarounds
          | boost::asio::ssl::context::no_sslv2
          | boost::asio::ssl::context::single_dh_use);
      context_.set_password_callback(boost::bind(&amp;server::get_password, this));
      context_.use_certificate_chain_file("server.crt");
      context_.use_private_key_file("server.key", boost::asio::ssl::context::pem);
      context_.use_tmp_dh_file("dh512.pem");
  #endif
      start_accept();
    }
  
    std::string get_password() const
    {
      return "test";
    }
  
    void start_accept()
    {
      session* new_session = new session(io_service_, context_);
      acceptor_.async_accept(new_session-&gt;socket(),
          boost::bind(&amp;server::handle_accept, this, new_session,
            boost::asio::placeholders::error));
    }
  
    void handle_accept(session* new_session,
        const boost::system::error_code&amp; error)
    {
      if (!error)
      {
        new_session-&gt;start();
      }
      else
      {
        delete new_session;
      }
  
      start_accept();
    }
  
  private:
    boost::asio::io_service&amp; io_service_;
    boost::asio::ip::tcp::acceptor acceptor_;
    boost::asio::ssl::context context_;
  };
  
  int main(int argc, char* argv[])
  {
    try
    {
      boost::asio::io_service io_service;
  
      using namespace std; // For atoi.
      server s(io_service, 7777 /*atoi(argv[1])*/);
  
      io_service.run();
    }
    catch (std::exception&amp; e)
    {
      std::cerr &lt;&lt; "Exception: " &lt;&lt; e.what() &lt;&lt; "\n";
    }
  
    return 0;
  }
  </code></pre>
  
  <p>I use boost 1.49 and OpenSSL 1.0.0i-fips 19 Apr 2012. I tried investigating this problem as much as possible, the last time I had this problem (a couple of months ago), I received an error number that I could trace to this error message: <code>error: decryption failed or bad record mac</code>.</p>
  
  <p>But I have no idea what is going wrong and how to fix this, any suggestions are welcome.</p>