GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_http_common-inl.h Lines: 67 86 77.9 %
Date: 2022-08-30 04:20:47 Branches: 15 26 57.7 %

Line Branch Exec Source
1
#ifndef SRC_NODE_HTTP_COMMON_INL_H_
2
#define SRC_NODE_HTTP_COMMON_INL_H_
3
4
#include "node_http_common.h"
5
#include "node.h"
6
#include "node_mem-inl.h"
7
#include "env-inl.h"
8
#include "v8.h"
9
10
#include <algorithm>
11
12
namespace node {
13
14
template <typename T>
15
23956
NgHeaders<T>::NgHeaders(Environment* env, v8::Local<v8::Array> headers) {
16
  v8::Local<v8::Value> header_string =
17
47912
      headers->Get(env->context(), 0).ToLocalChecked();
18
  v8::Local<v8::Value> header_count =
19
47912
      headers->Get(env->context(), 1).ToLocalChecked();
20
23956
  CHECK(header_count->IsUint32());
21
47912
  CHECK(header_string->IsString());
22
23956
  count_ = header_count.As<v8::Uint32>()->Value();
23
23956
  int header_string_len = header_string.As<v8::String>()->Length();
24
25
23956
  if (count_ == 0) {
26
31
    CHECK_EQ(header_string_len, 0);
27
32
    return;
28
  }
29
30
47850
  buf_.AllocateSufficientStorage((alignof(nv_t) - 1) +
31
23925
                                 count_ * sizeof(nv_t) +
32
                                 header_string_len);
33
34
23925
  char* start = AlignUp(buf_.out(), alignof(nv_t));
35
23925
  char* header_contents = start + (count_ * sizeof(nv_t));
36
23925
  nv_t* const nva = reinterpret_cast<nv_t*>(start);
37
38
23925
  CHECK_LE(header_contents + header_string_len, *buf_ + buf_.length());
39
23925
  CHECK_EQ(header_string.As<v8::String>()->WriteOneByte(
40
               env->isolate(),
41
               reinterpret_cast<uint8_t*>(header_contents),
42
               0,
43
               header_string_len,
44
               v8::String::NO_NULL_TERMINATION),
45
           header_string_len);
46
47
23925
  size_t n = 0;
48
  char* p;
49
97372
  for (p = header_contents; p < header_contents + header_string_len; n++) {
50
73448
    if (n >= count_) {
51
      static uint8_t zero = '\0';
52
1
      nva[0].name = nva[0].value = &zero;
53
1
      nva[0].namelen = nva[0].valuelen = 1;
54
1
      count_ = 1;
55
1
      return;
56
    }
57
58
73447
    nva[n].name = reinterpret_cast<uint8_t*>(p);
59
73447
    nva[n].namelen = strlen(p);
60
73447
    p += nva[n].namelen + 1;
61
73447
    nva[n].value = reinterpret_cast<uint8_t*>(p);
62
73447
    nva[n].valuelen = strlen(p);
63
73447
    p += nva[n].valuelen + 1;
64
73447
    nva[n].flags = *p;
65
73447
    p++;
66
  }
67
}
68
69
377
size_t GetClientMaxHeaderPairs(size_t max_header_pairs) {
70
  static constexpr size_t min_header_pairs = 1;
71
377
  return std::max(max_header_pairs, min_header_pairs);
72
}
73
74
393
size_t GetServerMaxHeaderPairs(size_t max_header_pairs) {
75
  static constexpr size_t min_header_pairs = 4;
76
393
  return std::max(max_header_pairs, min_header_pairs);
77
}
78
79
template <typename allocator_t>
80
std::string NgHeaderBase<allocator_t>::ToString() const {
81
  std::string ret = name();
82
  ret += " = ";
83
  ret += value();
84
  return ret;
85
}
86
87
template <typename T>
88
bool NgHeader<T>::IsZeroLength(
89
    NgHeader<T>::rcbuf_t* name,
90
    NgHeader<T>::rcbuf_t* value) {
91
  return IsZeroLength(-1, name, value);
92
}
93
94
template <typename T>
95
bool NgHeader<T>::IsZeroLength(
96
    int32_t token,
97
    NgHeader<T>::rcbuf_t* name,
98
    NgHeader<T>::rcbuf_t* value) {
99
100
  if (NgHeader<T>::rcbufferpointer_t::IsZeroLength(value))
101
    return true;
102
103
  const char* header_name = T::ToHttpHeaderName(token);
104
  return header_name != nullptr ||
105
      NgHeader<T>::rcbufferpointer_t::IsZeroLength(name);
106
}
107
108
template <typename T>
109
72680
NgHeader<T>::NgHeader(
110
    Environment* env,
111
    NgHeader<T>::rcbuf_t* name,
112
    NgHeader<T>::rcbuf_t* value,
113
    uint8_t flags)
114
72680
    : NgHeader<T>(env, -1, name, value, flags) {}
115
116
template <typename T>
117
72680
NgHeader<T>::NgHeader(
118
    Environment* env,
119
    int32_t token,
120
    NgHeader<T>::rcbuf_t* name,
121
    NgHeader<T>::rcbuf_t* value,
122
72680
    uint8_t flags) : env_(env), token_(token), flags_(flags) {
123
72680
  if (token == -1) {
124
72680
    CHECK_NOT_NULL(name);
125
72680
    name_.reset(name, true);  // Internalizable
126
  }
127
72680
  CHECK_NOT_NULL(value);
128
72680
  name_.reset(name, true);  // Internalizable
129
72680
  value_.reset(value);
130
72680
}
131
132
template <typename T>
133
72725
NgHeader<T>::NgHeader(NgHeader<T>&& other) noexcept
134
72725
    : env_(other.env_),
135
72725
      name_(std::move(other.name_)),
136
72725
      value_(std::move(other.value_)),
137
72725
      token_(other.token_),
138
72725
      flags_(other.flags_) {
139
72725
  other.token_ = -1;
140
72725
  other.flags_ = 0;
141
72725
  other.env_ = nullptr;
142
72725
}
143
144
template <typename T>
145
void NgHeader<T>::MemoryInfo(MemoryTracker* tracker) const {
146
  tracker->TrackField("name", name_);
147
  tracker->TrackField("value", value_);
148
}
149
150
template <typename T>
151
72660
v8::MaybeLocal<v8::String> NgHeader<T>::GetName(
152
    NgHeader<T>::allocator_t* allocator) const {
153
154
  // Not all instances will support using token id's for header names.
155
  // HTTP/2 specifically does not support it.
156
72660
  const char* header_name = T::ToHttpHeaderName(token_);
157
158
  // If header_name is not nullptr, then it is a known header with
159
  // a statically defined name. We can safely internalize it here.
160
72660
  if (header_name != nullptr) {
161
    auto& static_str_map = env_->isolate_data()->static_str_map;
162
    v8::Eternal<v8::String> eternal = static_str_map[header_name];
163
    if (eternal.IsEmpty()) {
164
      v8::Local<v8::String> str = OneByteString(env_->isolate(), header_name);
165
      eternal.Set(env_->isolate(), str);
166
      return str;
167
    }
168
    return eternal.Get(env_->isolate());
169
  }
170
72660
  return rcbufferpointer_t::External::New(allocator, name_);
171
}
172
173
template <typename T>
174
72660
v8::MaybeLocal<v8::String> NgHeader<T>::GetValue(
175
    NgHeader<T>::allocator_t* allocator) const {
176
72660
  return rcbufferpointer_t::External::New(allocator, value_);
177
}
178
179
template <typename T>
180
std::string NgHeader<T>::name() const {
181
  return name_.str();
182
}
183
184
template <typename T>
185
std::string NgHeader<T>::value() const {
186
  return value_.str();
187
}
188
189
template <typename T>
190
72680
size_t NgHeader<T>::length() const {
191
72680
  return name_.len() + value_.len();
192
}
193
194
template <typename T>
195
72660
uint8_t NgHeader<T>::flags() const {
196
72660
  return flags_;
197
}
198
199
}  // namespace node
200
201
#endif  // SRC_NODE_HTTP_COMMON_INL_H_