blob: 8d23a55278a8a59cb321e2e84fb5ee3c0e115fda [file] [log] [blame]
#include "http2/adapter/nghttp2_util.h"
#include <cstdint>
#include "absl/strings/string_view.h"
#include "http2/adapter/http2_protocol.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
#include "common/platform/api/quiche_logging.h"
namespace http2 {
namespace adapter {
namespace {
void DeleteCallbacks(nghttp2_session_callbacks* callbacks) {
if (callbacks) {
nghttp2_session_callbacks_del(callbacks);
}
}
void DeleteSession(nghttp2_session* session) {
if (session) {
nghttp2_session_del(session);
}
}
} // namespace
nghttp2_session_callbacks_unique_ptr MakeCallbacksPtr(
nghttp2_session_callbacks* callbacks) {
return nghttp2_session_callbacks_unique_ptr(callbacks, DeleteCallbacks);
}
nghttp2_session_unique_ptr MakeSessionPtr(nghttp2_session* session) {
return nghttp2_session_unique_ptr(session, DeleteSession);
}
uint8_t* ToUint8Ptr(char* str) { return reinterpret_cast<uint8_t*>(str); }
uint8_t* ToUint8Ptr(const char* str) {
return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(str));
}
absl::string_view ToStringView(nghttp2_rcbuf* rc_buffer) {
nghttp2_vec buffer = nghttp2_rcbuf_get_buf(rc_buffer);
return absl::string_view(reinterpret_cast<const char*>(buffer.base),
buffer.len);
}
absl::string_view ToStringView(uint8_t* pointer, size_t length) {
return absl::string_view(reinterpret_cast<const char*>(pointer), length);
}
absl::string_view ToStringView(const uint8_t* pointer, size_t length) {
return absl::string_view(reinterpret_cast<const char*>(pointer), length);
}
std::vector<nghttp2_nv> GetNghttp2Nvs(absl::Span<const Header> headers) {
const int num_headers = headers.size();
auto nghttp2_nvs = std::vector<nghttp2_nv>(num_headers);
for (int i = 0; i < num_headers; ++i) {
nghttp2_nv header;
uint8_t flags = NGHTTP2_NV_FLAG_NONE;
const auto [name, no_copy_name] = GetStringView(headers[i].first);
header.name = ToUint8Ptr(name.data());
header.namelen = name.size();
if (no_copy_name) {
flags |= NGHTTP2_NV_FLAG_NO_COPY_NAME;
}
const auto [value, no_copy_value] = GetStringView(headers[i].second);
header.value = ToUint8Ptr(value.data());
header.valuelen = value.size();
if (no_copy_value) {
flags |= NGHTTP2_NV_FLAG_NO_COPY_VALUE;
}
header.flags = flags;
nghttp2_nvs.push_back(std::move(header));
}
return nghttp2_nvs;
}
std::vector<nghttp2_nv> GetResponseNghttp2Nvs(
const spdy::Http2HeaderBlock& headers,
absl::string_view response_code) {
// Allocate enough for all headers and also the :status pseudoheader.
const int num_headers = headers.size();
auto nghttp2_nvs = std::vector<nghttp2_nv>(num_headers + 1);
// Add the :status pseudoheader first.
nghttp2_nv status;
status.name = ToUint8Ptr(kHttp2StatusPseudoHeader);
status.namelen = strlen(kHttp2StatusPseudoHeader);
status.value = ToUint8Ptr(response_code.data());
status.valuelen = response_code.size();
status.flags = NGHTTP2_FLAG_NONE;
nghttp2_nvs.push_back(std::move(status));
// Add the remaining headers.
for (const auto header_pair : headers) {
nghttp2_nv header;
header.name = ToUint8Ptr(header_pair.first.data());
header.namelen = header_pair.first.size();
header.value = ToUint8Ptr(header_pair.second.data());
header.valuelen = header_pair.second.size();
header.flags = NGHTTP2_FLAG_NONE;
nghttp2_nvs.push_back(std::move(header));
}
return nghttp2_nvs;
}
Http2ErrorCode ToHttp2ErrorCode(uint32_t wire_error_code) {
if (wire_error_code > static_cast<int>(Http2ErrorCode::MAX_ERROR_CODE)) {
return Http2ErrorCode::INTERNAL_ERROR;
}
return static_cast<Http2ErrorCode>(wire_error_code);
}
} // namespace adapter
} // namespace http2