void SSLAdapter::flush() { //TraceL << "Flushing" << endl; if (!initialized()) { int r = SSL_connect(_ssl); if (r < 0) { TraceL << "Flush: Handle error" << endl; handleError(r); } return; } // Read any decrypted SSL data from the read BIO // NOTE: Overwriting the socket's raw SSL recv buffer int nread = 0; while ((nread = SSL_read(_ssl, _socket->_buffer.data(), _socket->_buffer.capacity())) > 0) { //_socket->_buffer.limit(nread); _socket->onRecv(mutableBuffer(_socket->_buffer.data(), nread)); } // Flush any pending outgoing data if (SSL_is_init_finished(_ssl)) { if (_bufferOut.size() > 0) { int r = SSL_write(_ssl, &_bufferOut[0], _bufferOut.size()); // causes the write_bio to fill up (which we need to flush) if (r < 0) { handleError(r); } _bufferOut.clear(); flushWriteBIO(); } } }
void SSLAdapter::handleError(int rc) { if (rc >= 0) return; int error = SSL_get_error(_ssl, rc); switch (error) { case SSL_ERROR_ZERO_RETURN: return; case SSL_ERROR_WANT_READ: flushWriteBIO(); break; case SSL_ERROR_WANT_WRITE: assert(0 && "TODO"); break; case SSL_ERROR_WANT_CONNECT: case SSL_ERROR_WANT_ACCEPT: case SSL_ERROR_WANT_X509_LOOKUP: assert(0 && "should not occur"); break; default: char buffer[256]; ERR_error_string_n(ERR_get_error(), buffer, sizeof(buffer)); std::string msg(buffer); throw std::runtime_error("SSL connection error: " + msg); break; } }
void SSLAdapter::flush() { TraceL << "Flushing" << endl; // Keep trying to handshake until initialized if (!ready()) return handshake(); // Read any decrypted remote data from SSL and emit to the app flushReadBIO(); // Write any local data to SSL for excryption if (_bufferOut.size() > 0) { int r = SSL_write(_ssl, &_bufferOut[0], _bufferOut.size()); // causes the write_bio to fill up // (which we need to flush) if (r < 0) { handleError(r); } _bufferOut.clear(); // flushWriteBIO(); } // Send any encrypted data from SSL to the remote peer flushWriteBIO(); }