1
#include "source/common/network/connection_impl_base.h"
2

            
3
namespace Envoy {
4
namespace Network {
5

            
6
13
void ConnectionImplBase::addIdToHashKey(std::vector<uint8_t>& hash_key, uint64_t connection_id) {
7
  // Pack the connection_id into sizeof(connection_id) uint8_t entries in the hash_key vector.
8
13
  hash_key.reserve(hash_key.size() + sizeof(connection_id));
9
117
  for (unsigned i = 0; i < sizeof(connection_id); ++i) {
10
104
    hash_key.push_back(0xFF & (connection_id >> (8 * i)));
11
104
  }
12
13
}
13

            
14
ConnectionImplBase::ConnectionImplBase(Event::Dispatcher& dispatcher, uint64_t id)
15
114316
    : dispatcher_(dispatcher), id_(id) {}
16

            
17
215027
void ConnectionImplBase::addConnectionCallbacks(ConnectionCallbacks& cb) {
18
215027
  callbacks_.push_back(&cb);
19
215027
}
20

            
21
93
void ConnectionImplBase::removeConnectionCallbacks(ConnectionCallbacks& callbacks) {
22
  // For performance/safety reasons we just clear the callback and do not resize the list
23
104
  for (auto& callback : callbacks_) {
24
104
    if (callback == &callbacks) {
25
93
      callback = nullptr;
26
93
      return;
27
93
    }
28
104
  }
29
93
}
30

            
31
OptRef<const StreamInfo::StreamInfo> ConnectionImplBase::trackedStream() const {
32
  return streamInfo();
33
}
34

            
35
11
void ConnectionImplBase::hashKey(std::vector<uint8_t>& hash) const { addIdToHashKey(hash, id()); }
36

            
37
55661
void ConnectionImplBase::setConnectionStats(const ConnectionStats& stats) {
38
55661
  connection_stats_ = std::make_unique<ConnectionStats>(stats);
39
55661
}
40

            
41
22209
void ConnectionImplBase::setDelayedCloseTimeout(std::chrono::milliseconds timeout) {
42
  // Validate that this is only called prior to issuing a close() or closeSocket().
43
22209
  ASSERT(delayed_close_timer_ == nullptr && state() == State::Open);
44
22209
  delayed_close_timeout_ = timeout;
45
22209
}
46

            
47
2400
void ConnectionImplBase::initializeDelayedCloseTimer() {
48
2400
  const auto timeout = delayed_close_timeout_.count();
49
2400
  ASSERT(delayed_close_timer_ == nullptr && timeout > 0);
50
2400
  delayed_close_timer_ = dispatcher_.createTimer([this]() -> void { onDelayedCloseTimeout(); });
51
2400
  ENVOY_CONN_LOG(debug, "setting delayed close timer with timeout {} ms", *this, timeout);
52
2400
  delayed_close_timer_->enableTimer(delayed_close_timeout_);
53
2400
}
54

            
55
197638
void ConnectionImplBase::raiseConnectionEvent(ConnectionEvent event) {
56
346301
  for (ConnectionCallbacks* callback : callbacks_) {
57
    // If a previous connected callback closed the connection, don't raise any further connected
58
    // events. There was already recursion raising closed events. We still raise closed events
59
    // to further callbacks because such events are typically used for cleanup.
60
345976
    if (event != ConnectionEvent::LocalClose && event != ConnectionEvent::RemoteClose &&
61
345976
        state() != State::Open) {
62
10
      return;
63
10
    }
64

            
65
345967
    if (callback != nullptr) {
66
345852
      callback->onEvent(event);
67
345852
    }
68
345966
  }
69
197638
}
70

            
71
1954
void ConnectionImplBase::onDelayedCloseTimeout() {
72
1954
  delayed_close_timer_.reset();
73
1954
  ENVOY_CONN_LOG(debug, "triggered delayed close", *this);
74
1954
  if (connection_stats_ != nullptr && connection_stats_->delayed_close_timeouts_ != nullptr) {
75
1946
    connection_stats_->delayed_close_timeouts_->inc();
76
1946
  }
77
1954
  closeConnectionImmediatelyWithDetails(
78
1954
      StreamInfo::LocalCloseReasons::get().TriggeredDelayedCloseTimeout);
79
1954
}
80

            
81
} // namespace Network
82
} // namespace Envoy