mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-07 20:28:10 +00:00
202 lines
5.5 KiB
C++
202 lines
5.5 KiB
C++
#ifndef SRC_NODE_HTTP_COMMON_INL_H_
|
|
#define SRC_NODE_HTTP_COMMON_INL_H_
|
|
|
|
#include "node_http_common.h"
|
|
#include "node.h"
|
|
#include "node_mem-inl.h"
|
|
#include "env-inl.h"
|
|
#include "v8.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace node {
|
|
|
|
template <typename T>
|
|
NgHeaders<T>::NgHeaders(Environment* env, v8::Local<v8::Array> headers) {
|
|
v8::Local<v8::Value> header_string =
|
|
headers->Get(env->context(), 0).ToLocalChecked();
|
|
v8::Local<v8::Value> header_count =
|
|
headers->Get(env->context(), 1).ToLocalChecked();
|
|
CHECK(header_count->IsUint32());
|
|
CHECK(header_string->IsString());
|
|
count_ = header_count.As<v8::Uint32>()->Value();
|
|
int header_string_len = header_string.As<v8::String>()->Length();
|
|
|
|
if (count_ == 0) {
|
|
CHECK_EQ(header_string_len, 0);
|
|
return;
|
|
}
|
|
|
|
buf_.AllocateSufficientStorage((alignof(nv_t) - 1) +
|
|
count_ * sizeof(nv_t) +
|
|
header_string_len);
|
|
|
|
char* start = AlignUp(buf_.out(), alignof(nv_t));
|
|
char* header_contents = start + (count_ * sizeof(nv_t));
|
|
nv_t* const nva = reinterpret_cast<nv_t*>(start);
|
|
|
|
CHECK_LE(header_contents + header_string_len, *buf_ + buf_.length());
|
|
CHECK_EQ(header_string.As<v8::String>()->WriteOneByte(
|
|
env->isolate(),
|
|
reinterpret_cast<uint8_t*>(header_contents),
|
|
0,
|
|
header_string_len,
|
|
v8::String::NO_NULL_TERMINATION),
|
|
header_string_len);
|
|
|
|
size_t n = 0;
|
|
char* p;
|
|
for (p = header_contents; p < header_contents + header_string_len; n++) {
|
|
if (n >= count_) {
|
|
static uint8_t zero = '\0';
|
|
nva[0].name = nva[0].value = &zero;
|
|
nva[0].namelen = nva[0].valuelen = 1;
|
|
count_ = 1;
|
|
return;
|
|
}
|
|
|
|
nva[n].name = reinterpret_cast<uint8_t*>(p);
|
|
nva[n].namelen = strlen(p);
|
|
p += nva[n].namelen + 1;
|
|
nva[n].value = reinterpret_cast<uint8_t*>(p);
|
|
nva[n].valuelen = strlen(p);
|
|
p += nva[n].valuelen + 1;
|
|
nva[n].flags = *p;
|
|
p++;
|
|
}
|
|
}
|
|
|
|
size_t GetClientMaxHeaderPairs(size_t max_header_pairs) {
|
|
static constexpr size_t min_header_pairs = 1;
|
|
return std::max(max_header_pairs, min_header_pairs);
|
|
}
|
|
|
|
size_t GetServerMaxHeaderPairs(size_t max_header_pairs) {
|
|
static constexpr size_t min_header_pairs = 4;
|
|
return std::max(max_header_pairs, min_header_pairs);
|
|
}
|
|
|
|
template <typename allocator_t>
|
|
std::string NgHeaderBase<allocator_t>::ToString() const {
|
|
std::string ret = name();
|
|
ret += " = ";
|
|
ret += value();
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
bool NgHeader<T>::IsZeroLength(
|
|
NgHeader<T>::rcbuf_t* name,
|
|
NgHeader<T>::rcbuf_t* value) {
|
|
return IsZeroLength(-1, name, value);
|
|
}
|
|
|
|
template <typename T>
|
|
bool NgHeader<T>::IsZeroLength(
|
|
int32_t token,
|
|
NgHeader<T>::rcbuf_t* name,
|
|
NgHeader<T>::rcbuf_t* value) {
|
|
|
|
if (NgHeader<T>::rcbufferpointer_t::IsZeroLength(value))
|
|
return true;
|
|
|
|
const char* header_name = T::ToHttpHeaderName(token);
|
|
return header_name != nullptr ||
|
|
NgHeader<T>::rcbufferpointer_t::IsZeroLength(name);
|
|
}
|
|
|
|
template <typename T>
|
|
NgHeader<T>::NgHeader(
|
|
Environment* env,
|
|
NgHeader<T>::rcbuf_t* name,
|
|
NgHeader<T>::rcbuf_t* value,
|
|
uint8_t flags)
|
|
: NgHeader<T>(env, -1, name, value, flags) {}
|
|
|
|
template <typename T>
|
|
NgHeader<T>::NgHeader(
|
|
Environment* env,
|
|
int32_t token,
|
|
NgHeader<T>::rcbuf_t* name,
|
|
NgHeader<T>::rcbuf_t* value,
|
|
uint8_t flags) : env_(env), token_(token), flags_(flags) {
|
|
if (token == -1) {
|
|
CHECK_NOT_NULL(name);
|
|
name_.reset(name, true); // Internalizable
|
|
}
|
|
CHECK_NOT_NULL(value);
|
|
name_.reset(name, true); // Internalizable
|
|
value_.reset(value);
|
|
}
|
|
|
|
template <typename T>
|
|
NgHeader<T>::NgHeader(NgHeader<T>&& other) noexcept
|
|
: env_(other.env_),
|
|
name_(std::move(other.name_)),
|
|
value_(std::move(other.value_)),
|
|
token_(other.token_),
|
|
flags_(other.flags_) {
|
|
other.token_ = -1;
|
|
other.flags_ = 0;
|
|
other.env_ = nullptr;
|
|
}
|
|
|
|
template <typename T>
|
|
void NgHeader<T>::MemoryInfo(MemoryTracker* tracker) const {
|
|
tracker->TrackField("name", name_);
|
|
tracker->TrackField("value", value_);
|
|
}
|
|
|
|
template <typename T>
|
|
v8::MaybeLocal<v8::String> NgHeader<T>::GetName(
|
|
NgHeader<T>::allocator_t* allocator) const {
|
|
|
|
// Not all instances will support using token id's for header names.
|
|
// HTTP/2 specifically does not support it.
|
|
const char* header_name = T::ToHttpHeaderName(token_);
|
|
|
|
// If header_name is not nullptr, then it is a known header with
|
|
// a statically defined name. We can safely internalize it here.
|
|
if (header_name != nullptr) {
|
|
auto& static_str_map = env_->isolate_data()->static_str_map;
|
|
v8::Eternal<v8::String> eternal = static_str_map[header_name];
|
|
if (eternal.IsEmpty()) {
|
|
v8::Local<v8::String> str = OneByteString(env_->isolate(), header_name);
|
|
eternal.Set(env_->isolate(), str);
|
|
return str;
|
|
}
|
|
return eternal.Get(env_->isolate());
|
|
}
|
|
return rcbufferpointer_t::External::New(allocator, name_);
|
|
}
|
|
|
|
template <typename T>
|
|
v8::MaybeLocal<v8::String> NgHeader<T>::GetValue(
|
|
NgHeader<T>::allocator_t* allocator) const {
|
|
return rcbufferpointer_t::External::New(allocator, value_);
|
|
}
|
|
|
|
template <typename T>
|
|
std::string NgHeader<T>::name() const {
|
|
return name_.str();
|
|
}
|
|
|
|
template <typename T>
|
|
std::string NgHeader<T>::value() const {
|
|
return value_.str();
|
|
}
|
|
|
|
template <typename T>
|
|
size_t NgHeader<T>::length() const {
|
|
return name_.len() + value_.len();
|
|
}
|
|
|
|
template <typename T>
|
|
uint8_t NgHeader<T>::flags() const {
|
|
return flags_;
|
|
}
|
|
|
|
} // namespace node
|
|
|
|
#endif // SRC_NODE_HTTP_COMMON_INL_H_
|