Repository: envoyproxy/envoy
File: source/common/network/connection_impl.cc (C++)

Code before:
    return;
  }

  // The connection is closed by Envoy by sending RST, and the connection is closed immediately.
  if (type == ConnectionCloseType::AbortReset) {
    ENVOY_CONN_LOG(
        trace, "connection closing type=AbortReset, setting LocalReset to the detected close type.",
        *this);
    setDetectedCloseType(StreamInfo::DetectedCloseType::LocalReset);
    closeSocket(ConnectionEvent::LocalClose);
    ensureAccessLogWritten();
    return;
  }

  if (type == ConnectionCloseType::Abort || type == ConnectionCloseType::NoFlush) {
    closeInternal(type);
    ensureAccessLogWritten();
    return;
  }

  // Only FlushWrite and FlushWriteAndDelay are managed by the filter manager, since the above
  // status will abort data naturally.
  ASSERT(type == ConnectionCloseType::FlushWrite ||
         type == ConnectionCloseType::FlushWriteAndDelay);
  closeThroughFilterManager(ConnectionCloseAction{ConnectionEvent::LocalClose, false, type});
  ensureAccessLogWritten();
}

void ConnectionImpl::closeInternal(ConnectionCloseType type) {
  if (!socket_->isOpen()) {
    return;
  }

  uint64_t data_to_write = write_buffer_->length();
  ENVOY_CONN_LOG_EVENT(debug, "connection_closing", "closing data_to_write={} type={}", *this,
                       data_to_write, enumToInt(type));

  const bool delayed_close_timeout_set = delayed_close_timeout_.count() > 0;
  if (data_to_write == 0 || type == ConnectionCloseType::NoFlush ||
      type == ConnectionCloseType::Abort || !transport_socket_->canFlushClose()) {
    if (data_to_write > 0 && type != ConnectionCloseType::Abort) {
      // We aren't going to wait to flush, but try to write as much as we can if there is pending
      // data.
      transport_socket_->doWrite(*write_buffer_, true);
    }

    if (type != ConnectionCloseType::FlushWriteAndDelay || !delayed_close_timeout_set) {
      closeConnectionImmediately();
      return;
    }
    // The socket is being closed and either there is no more data to write or the data can not be

Review comment (suggestion):
Actually the `closeThroughFilterManager` can defer the close if there is still data pending in the flight, and logging here could make the streamInfo inconsistent with the final state. Just adding `ensureAccessLogWritten` to `close()` will also not cover the remote close. We could move it to the end of `closeSocket()` 

Code after:
                         *this);
    return;
  }

  // The connection is closed by Envoy by sending RST, and the connection is closed immediately.
  if (type == ConnectionCloseType::AbortReset) {
    ENVOY_CONN_LOG(
        trace, "connection closing type=AbortReset, setting LocalReset to the detected close type.",
        *this);
    setDetectedCloseType(StreamInfo::DetectedCloseType::LocalReset);
    closeSocket(ConnectionEvent::LocalClose);
    return;
  }

  if (type == ConnectionCloseType::Abort || type == ConnectionCloseType::NoFlush) {
    closeInternal(type);
    return;
  }

  // Only FlushWrite and FlushWriteAndDelay are managed by the filter manager, since the above
  // status will abort data naturally.
  ASSERT(type == ConnectionCloseType::FlushWrite ||
         type == ConnectionCloseType::FlushWriteAndDelay);
  closeThroughFilterManager(ConnectionCloseAction{ConnectionEvent::LocalClose, false, type});
}

void ConnectionImpl::closeInternal(ConnectionCloseType type) {
  if (!socket_->isOpen()) {
    return;
  }

  uint64_t data_to_write = write_buffer_->length();
  ENVOY_CONN_LOG_EVENT(debug, "connection_closing", "closing data_to_write={} type={}", *this,
                       data_to_write, enumToInt(type));

  const bool delayed_close_timeout_set = delayed_close_timeout_.count() > 0;
  if (data_to_write == 0 || type == ConnectionCloseType::NoFlush ||
      type == ConnectionCloseType::Abort || !transport_socket_->canFlushClose()) {
    if (data_to_write > 0 && type != ConnectionCloseType::Abort) {
      // We aren't going to wait to flush, but try to write as much as we can if there is pending
      // data.
      transport_socket_->doWrite(*write_buffer_, true);
    }

    if (type != ConnectionCloseType::FlushWriteAndDelay || !delayed_close_timeout_set) {
      closeConnectionImmediately();
      return;
    }
    // The socket is being closed and either there is no more data to write or the data can not be
    // flushed (!transport_socket_->canFlushClose()). Since a delayed close has been requested,
    // start the delayed close timer if it hasn't been done already by a previous close().