1
// NOLINT(namespace-envoy)
2

            
3
#include "source/common/http/header_utility.h"
4
#include "source/extensions/dynamic_modules/abi/abi.h"
5
#include "source/extensions/upstreams/http/dynamic_modules/upstream_request.h"
6

            
7
namespace {
8

            
9
Envoy::Extensions::Upstreams::Http::DynamicModules::HttpTcpBridge*
10
43
getBridge(envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr) {
11
43
  return static_cast<Envoy::Extensions::Upstreams::Http::DynamicModules::HttpTcpBridge*>(
12
43
      bridge_envoy_ptr);
13
43
}
14

            
15
void fillBufferChunks(const Envoy::Buffer::Instance& buffer,
16
3
                      envoy_dynamic_module_type_envoy_buffer* result_buffer_vector) {
17
3
  Envoy::Buffer::RawSliceVector raw_slices = buffer.getRawSlices();
18
3
  size_t counter = 0;
19
3
  for (const auto& slice : raw_slices) {
20
3
    result_buffer_vector[counter].length = slice.len_;
21
3
    result_buffer_vector[counter].ptr = static_cast<char*>(slice.mem_);
22
3
    counter++;
23
3
  }
24
3
}
25

            
26
} // namespace
27

            
28
extern "C" {
29

            
30
// ----------------------- Request Header Operations ---------------------------
31

            
32
bool envoy_dynamic_module_callback_upstream_http_tcp_bridge_get_request_header(
33
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
34
    envoy_dynamic_module_type_module_buffer key, envoy_dynamic_module_type_envoy_buffer* result,
35
4
    size_t index, size_t* total_count_out) {
36
4
  auto* bridge = getBridge(bridge_envoy_ptr);
37
4
  const auto* headers = bridge->requestHeaders();
38
4
  if (headers == nullptr) {
39
1
    *result = {.ptr = nullptr, .length = 0};
40
1
    if (total_count_out != nullptr) {
41
1
      *total_count_out = 0;
42
1
    }
43
1
    return false;
44
1
  }
45

            
46
3
  absl::string_view key_view(key.ptr, key.length);
47
3
  const auto values = headers->get(Envoy::Http::LowerCaseString(key_view));
48
3
  if (total_count_out != nullptr) {
49
2
    *total_count_out = values.size();
50
2
  }
51

            
52
3
  if (index >= values.size()) {
53
1
    *result = {.ptr = nullptr, .length = 0};
54
1
    return false;
55
1
  }
56

            
57
2
  const auto value = values[index]->value().getStringView();
58
2
  *result = {.ptr = const_cast<char*>(value.data()), .length = value.size()};
59
2
  return true;
60
3
}
61

            
62
size_t envoy_dynamic_module_callback_upstream_http_tcp_bridge_get_request_headers_size(
63
6
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr) {
64
6
  auto* bridge = getBridge(bridge_envoy_ptr);
65
6
  const auto* headers = bridge->requestHeaders();
66
6
  return headers != nullptr ? headers->size() : 0;
67
6
}
68

            
69
bool envoy_dynamic_module_callback_upstream_http_tcp_bridge_get_request_headers(
70
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
71
5
    envoy_dynamic_module_type_envoy_http_header* result_headers) {
72
5
  auto* bridge = getBridge(bridge_envoy_ptr);
73
5
  const auto* headers = bridge->requestHeaders();
74
5
  if (headers == nullptr) {
75
1
    return false;
76
1
  }
77
4
  size_t i = 0;
78
4
  headers->iterate([&i, &result_headers](
79
9
                       const Envoy::Http::HeaderEntry& header) -> Envoy::Http::HeaderMap::Iterate {
80
9
    auto& key = header.key();
81
9
    result_headers[i].key_ptr = const_cast<char*>(key.getStringView().data());
82
9
    result_headers[i].key_length = key.size();
83
9
    auto& value = header.value();
84
9
    result_headers[i].value_ptr = const_cast<char*>(value.getStringView().data());
85
9
    result_headers[i].value_length = value.size();
86
9
    i++;
87
9
    return Envoy::Http::HeaderMap::Iterate::Continue;
88
9
  });
89
4
  return true;
90
5
}
91

            
92
// ----------------------- Request Buffer Operations ---------------------------
93

            
94
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_get_request_buffer(
95
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
96
8
    envoy_dynamic_module_type_envoy_buffer* result_buffer, size_t* result_buffer_length) {
97
8
  auto* bridge = getBridge(bridge_envoy_ptr);
98
8
  auto* buffer = bridge->requestBuffer();
99
8
  if (buffer == nullptr || buffer->length() == 0) {
100
6
    *result_buffer_length = 0;
101
6
    return;
102
6
  }
103
2
  fillBufferChunks(*buffer, result_buffer);
104
2
  *result_buffer_length = buffer->getRawSlices(std::nullopt).size();
105
2
}
106

            
107
// ----------------------- Response Buffer Operations --------------------------
108

            
109
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_get_response_buffer(
110
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
111
3
    envoy_dynamic_module_type_envoy_buffer* result_buffer, size_t* result_buffer_length) {
112
3
  auto* bridge = getBridge(bridge_envoy_ptr);
113
3
  auto* buffer = bridge->responseBuffer();
114
3
  if (buffer == nullptr || buffer->length() == 0) {
115
2
    *result_buffer_length = 0;
116
2
    return;
117
2
  }
118
1
  fillBufferChunks(*buffer, result_buffer);
119
1
  *result_buffer_length = buffer->getRawSlices(std::nullopt).size();
120
1
}
121

            
122
// ----------------------- Send Upstream Data ----------------------------------
123

            
124
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_send_upstream_data(
125
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
126
4
    envoy_dynamic_module_type_module_buffer data, bool end_stream) {
127
4
  auto* bridge = getBridge(bridge_envoy_ptr);
128
4
  bridge->sendUpstreamData(absl::string_view(data.ptr, data.length), end_stream);
129
4
}
130

            
131
// ----------------------- Send Response Operations ----------------------------
132

            
133
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_send_response(
134
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
135
    uint32_t status_code, envoy_dynamic_module_type_module_http_header* headers_vector,
136
6
    size_t headers_vector_size, envoy_dynamic_module_type_module_buffer body) {
137
6
  auto* bridge = getBridge(bridge_envoy_ptr);
138
6
  bridge->sendResponse(status_code, headers_vector, headers_vector_size,
139
6
                       absl::string_view(body.ptr, body.length));
140
6
}
141

            
142
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_send_response_headers(
143
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
144
    uint32_t status_code, envoy_dynamic_module_type_module_http_header* headers_vector,
145
3
    size_t headers_vector_size, bool end_stream) {
146
3
  auto* bridge = getBridge(bridge_envoy_ptr);
147
3
  bridge->sendResponseHeaders(status_code, headers_vector, headers_vector_size, end_stream);
148
3
}
149

            
150
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_send_response_data(
151
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
152
4
    envoy_dynamic_module_type_module_buffer data, bool end_stream) {
153
4
  auto* bridge = getBridge(bridge_envoy_ptr);
154
4
  bridge->sendResponseData(absl::string_view(data.ptr, data.length), end_stream);
155
4
}
156

            
157
void envoy_dynamic_module_callback_upstream_http_tcp_bridge_send_response_trailers(
158
    envoy_dynamic_module_type_upstream_http_tcp_bridge_envoy_ptr bridge_envoy_ptr,
159
    envoy_dynamic_module_type_module_http_header* trailers_vector, size_t trailers_vector_size) {
160
  auto* bridge = getBridge(bridge_envoy_ptr);
161
  bridge->sendResponseTrailers(trailers_vector, trailers_vector_size);
162
}
163

            
164
} // extern "C"