1
#include "source/extensions/bootstrap/reverse_tunnel/common/reverse_connection_utility.h"
2

            
3
#include "source/common/buffer/buffer_impl.h"
4
#include "source/common/common/assert.h"
5
#include "source/common/common/logger.h"
6

            
7
#include "absl/strings/str_cat.h"
8

            
9
namespace Envoy {
10
namespace Extensions {
11
namespace Bootstrap {
12
namespace ReverseConnection {
13

            
14
48
bool ReverseConnectionUtility::isPingMessage(absl::string_view data) {
15
48
  if (data.size() != PING_MESSAGE.size()) {
16
10
    return false;
17
10
  }
18
38
  return ::memcmp(data.data(), PING_MESSAGE.data(), PING_MESSAGE.size()) == 0;
19
48
}
20

            
21
18
Buffer::InstancePtr ReverseConnectionUtility::createPingResponse() {
22
18
  return std::make_unique<Buffer::OwnedImpl>(PING_MESSAGE);
23
18
}
24

            
25
7
bool ReverseConnectionUtility::sendPingResponse(Network::Connection& connection) {
26
7
  auto ping_buffer = createPingResponse();
27
7
  connection.write(*ping_buffer, false);
28
7
  ENVOY_LOG(trace, "Reverse connection utility: sent RPING response on connection {}.",
29
7
            connection.id());
30
7
  return true;
31
7
}
32

            
33
5
Api::IoCallUint64Result ReverseConnectionUtility::sendPingResponse(Network::IoHandle& io_handle) {
34
5
  auto ping_buffer = createPingResponse();
35
5
  Api::IoCallUint64Result result = io_handle.write(*ping_buffer);
36
5
  if (result.ok()) {
37
4
    ENVOY_LOG(trace, "Reverse connection utility: sent RPING response. bytes: {}.",
38
4
              result.return_value_);
39
4
  } else {
40
1
    ENVOY_LOG(trace, "Reverse connection utility: failed to send RPING response. error: {}.",
41
1
              result.err_->getErrorDetails());
42
1
  }
43
5
  return result;
44
5
}
45

            
46
bool ReverseConnectionUtility::handlePingMessage(absl::string_view data,
47
3
                                                 Network::Connection& connection) {
48
3
  if (!isPingMessage(data)) {
49
2
    return false;
50
2
  }
51
1
  ENVOY_LOG(trace, "Reverse connection utility: received RPING on connection {}; echoing back.",
52
1
            connection.id());
53
1
  return sendPingResponse(connection);
54
3
}
55

            
56
6
bool ReverseConnectionUtility::extractPingFromHttpData(absl::string_view http_data) {
57
6
  if (http_data.find(PING_MESSAGE) != absl::string_view::npos) {
58
3
    ENVOY_LOG(trace, "Reverse connection utility: found RPING in HTTP data.");
59
3
    return true;
60
3
  }
61
3
  return false;
62
6
}
63

            
64
ReverseConnectionUtility::TenantScopedIdentifierView
65
35
ReverseConnectionUtility::splitTenantScopedIdentifier(absl::string_view value) {
66
35
  const size_t pos = value.find(TENANT_SCOPE_DELIMITER);
67
35
  if (pos == absl::string_view::npos) {
68
2
    return {absl::string_view(), value};
69
2
  }
70
33
  return {value.substr(0, pos), value.substr(pos + TENANT_SCOPE_DELIMITER.size())};
71
35
}
72

            
73
std::string ReverseConnectionUtility::buildTenantScopedIdentifier(absl::string_view tenant,
74
14
                                                                  absl::string_view identifier) {
75
14
  if (tenant.empty()) {
76
1
    return std::string(identifier);
77
1
  }
78
13
  return std::string(absl::StrCat(tenant, TENANT_SCOPE_DELIMITER, identifier));
79
14
}
80

            
81
6
std::shared_ptr<PingMessageHandler> ReverseConnectionMessageHandlerFactory::createPingHandler() {
82
6
  return std::make_shared<PingMessageHandler>();
83
6
}
84

            
85
bool PingMessageHandler::processPingMessage(absl::string_view data,
86
7
                                            Network::Connection& connection) {
87
7
  if (ReverseConnectionUtility::isPingMessage(data)) {
88
5
    ++ping_count_;
89
5
    ENVOY_LOG(debug, "reverse_tunnel: processing ping #{} on connection {}", ping_count_,
90
5
              connection.id());
91
5
    return ReverseConnectionUtility::sendPingResponse(connection);
92
5
  }
93
2
  return false;
94
7
}
95

            
96
} // namespace ReverseConnection
97
} // namespace Bootstrap
98
} // namespace Extensions
99
} // namespace Envoy