int AsyncSSLSocket::bioRead(BIO* b, char* out, int outl) {
  if (!out) {
    return 0;
  }
  BIO_clear_retry_flags(b);

  auto appData = OpenSSLUtils::getBioAppData(b);
  CHECK(appData);
  auto sslSock = reinterpret_cast<AsyncSSLSocket*>(appData);

  if (sslSock->preReceivedData_ && !sslSock->preReceivedData_->empty()) {
    VLOG(5) << "AsyncSSLSocket::bioRead() this=" << sslSock
            << ", reading pre-received data";

    Cursor cursor(sslSock->preReceivedData_.get());
    auto len = cursor.pullAtMost(out, outl);

    IOBufQueue queue;
    queue.append(std::move(sslSock->preReceivedData_));
    queue.trimStart(len);
    sslSock->preReceivedData_ = queue.move();
    return static_cast<int>(len);
  } else {
    auto result = int(netops::recv(OpenSSLUtils::getBioFd(b), out, outl, 0));
    if (result <= 0 && OpenSSLUtils::getBioShouldRetryWrite(result)) {
      BIO_set_retry_read(b);
    }
    return result;
  }
}
int AsyncSSLSocket::bioRead(BIO* b, char* out, int outl) {
  if (!out) {
    return 0;
  }
  BIO_clear_retry_flags(b);

  auto appData = OpenSSLUtils::getBioAppData(b);
  CHECK(appData);
  auto sslSock = reinterpret_cast<AsyncSSLSocket*>(appData);

  if (sslSock->preReceivedData_ && !sslSock->preReceivedData_->empty()) {
    VLOG(5) << "AsyncSSLSocket::bioRead() this=" << sslSock
            << ", reading pre-received data";

    Cursor cursor(sslSock->preReceivedData_.get());
    auto len = cursor.pullAtMost(out, outl);

    IOBufQueue queue;
    queue.append(std::move(sslSock->preReceivedData_));
    queue.trimStart(len);
    sslSock->preReceivedData_ = queue.move();
    return static_cast<int>(len);
  } else {
    auto result = int(netops::recv(OpenSSLUtils::getBioFd(b), out, outl, 0));
    if (result <= 0 && OpenSSLUtils::getBioShouldRetryWrite(result)) {
      BIO_set_retry_read(b);
    }
    return result;
  }
}