int AsyncSSLSocket::bioWrite(BIO* b, const char* in, int inl) {
  struct msghdr msg;
  struct iovec iov;
  AsyncSSLSocket* tsslSock;

  iov.iov_base = const_cast<char*>(in);
  iov.iov_len = size_t(inl);
  memset(&msg, 0, sizeof(msg));
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  auto appData = OpenSSLUtils::getBioAppData(b);
  CHECK(appData);

  tsslSock = reinterpret_cast<AsyncSSLSocket*>(appData);
  CHECK(tsslSock);

  WriteFlags flags = WriteFlags::NONE;
  if (tsslSock->isEorTrackingEnabled() && tsslSock->minEorRawByteNo_ &&
      tsslSock->minEorRawByteNo_ <= BIO_number_written(b) + inl) {
    flags |= tsslSock->appEorByteWriteFlags_;
  }

  if (tsslSock->corkCurrentWrite_) {
    flags |= WriteFlags::CORK;
  }

  int msg_flags = tsslSock->getSendMsgParamsCB()->getFlags(
      flags, false /*zeroCopyEnabled*/);
  msg.msg_controllen =
      tsslSock->getSendMsgParamsCB()->getAncillaryDataSize(flags);
  CHECK_GE(
      AsyncSocket::SendMsgParamsCallback::maxAncillaryDataSize,
      msg.msg_controllen);
  if (msg.msg_controllen != 0) {
    msg.msg_control = reinterpret_cast<char*>(alloca(msg.msg_controllen));
    tsslSock->getSendMsgParamsCB()->getAncillaryData(flags, msg.msg_control);
  }

  auto result =
      tsslSock->sendSocketMessage(OpenSSLUtils::getBioFd(b), &msg, msg_flags);
  BIO_clear_retry_flags(b);
  if (!result.exception && result.writeReturn <= 0) {
    if (OpenSSLUtils::getBioShouldRetryWrite(int(result.writeReturn))) {
      BIO_set_retry_write(b);
    }
  }
  return int(result.writeReturn);
}
int AsyncSSLSocket::bioWrite(BIO* b, const char* in, int inl) {
  struct msghdr msg;
  struct iovec iov;
  AsyncSSLSocket* tsslSock;

  iov.iov_base = const_cast<char*>(in);
  iov.iov_len = size_t(inl);
  memset(&msg, 0, sizeof(msg));
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  auto appData = OpenSSLUtils::getBioAppData(b);
  CHECK(appData);

  tsslSock = reinterpret_cast<AsyncSSLSocket*>(appData);
  CHECK(tsslSock);

  WriteFlags flags = WriteFlags::NONE;
  if (tsslSock->isEorTrackingEnabled() && tsslSock->minEorRawByteNo_ &&
      tsslSock->minEorRawByteNo_ <= BIO_number_written(b) + inl) {
    flags |= tsslSock->appEorByteWriteFlags_;
  }

  if (tsslSock->corkCurrentWrite_) {
    flags |= WriteFlags::CORK;
  }

  int msg_flags = tsslSock->getSendMsgParamsCB()->getFlags(
      flags, false  );
  msg.msg_controllen =
      tsslSock->getSendMsgParamsCB()->getAncillaryDataSize(flags);
  CHECK_GE(
      AsyncSocket::SendMsgParamsCallback::maxAncillaryDataSize,
      msg.msg_controllen);
  if (msg.msg_controllen != 0) {
    msg.msg_control = reinterpret_cast<char*>(alloca(msg.msg_controllen));
    tsslSock->getSendMsgParamsCB()->getAncillaryData(flags, msg.msg_control);
  }

  auto result =
      tsslSock->sendSocketMessage(OpenSSLUtils::getBioFd(b), &msg, msg_flags);
  BIO_clear_retry_flags(b);
  if (!result.exception && result.writeReturn <= 0) {
    if (OpenSSLUtils::getBioShouldRetryWrite(int(result.writeReturn))) {
      BIO_set_retry_write(b);
    }
  }
  return int(result.writeReturn);
}