GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/cares_wrap.h Lines: 155 183 84.7 %
Date: 2021-05-26 04:16:18 Branches: 120 471 25.5 %

Line Branch Exec Source
1
#ifndef SRC_CARES_WRAP_H_
2
#define SRC_CARES_WRAP_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#define CARES_STATICLIB
7
8
#include "async_wrap.h"
9
#include "base_object.h"
10
#include "env.h"
11
#include "memory_tracker.h"
12
#include "util.h"
13
#include "node.h"
14
15
#include "ares.h"
16
#include "v8.h"
17
#include "uv.h"
18
19
#include <unordered_set>
20
21
#ifdef __POSIX__
22
# include <netdb.h>
23
#endif  // __POSIX__
24
25
#if defined(__ANDROID__) || \
26
    defined(__MINGW32__) || \
27
    defined(__OpenBSD__) || \
28
    defined(_MSC_VER)
29
30
# include <nameser.h>
31
#else
32
# include <arpa/nameser.h>
33
#endif
34
35
namespace node {
36
namespace cares_wrap {
37
38
constexpr int ns_t_cname_or_a = -1;
39
constexpr int DNS_ESETSRVPENDING = -1000;
40
41
class ChannelWrap;
42
43
inline void safe_free_hostent(struct hostent* host);
44
45
using HostEntPointer = DeleteFnPtr<hostent, ares_free_hostent>;
46
using SafeHostEntPointer = DeleteFnPtr<hostent, safe_free_hostent>;
47
48
33
inline const char* ToErrorCodeString(int status) {
49






33
  switch (status) {
50
#define V(code) case ARES_##code: return #code;
51
    V(EADDRGETNETWORKPARAMS)
52
    V(EBADFAMILY)
53
    V(EBADFLAGS)
54
    V(EBADHINTS)
55
    V(EBADNAME)
56
    V(EBADQUERY)
57
2
    V(EBADRESP)
58
    V(EBADSTR)
59
24
    V(ECANCELLED)
60
    V(ECONNREFUSED)
61
    V(EDESTRUCTION)
62
    V(EFILE)
63
    V(EFORMERR)
64
    V(ELOADIPHLPAPI)
65
    V(ENODATA)
66
    V(ENOMEM)
67
    V(ENONAME)
68
1
    V(ENOTFOUND)
69
    V(ENOTIMP)
70
    V(ENOTINITIALIZED)
71
    V(EOF)
72
    V(EREFUSED)
73
    V(ESERVFAIL)
74
6
    V(ETIMEOUT)
75
#undef V
76
  }
77
78
  return "UNKNOWN_ARES_ERROR";
79
}
80
81
2
inline void cares_wrap_hostent_cpy(
82
    struct hostent* dest,
83
    const struct hostent* src) {
84
2
  dest->h_addr_list = nullptr;
85
2
  dest->h_addrtype = 0;
86
2
  dest->h_aliases = nullptr;
87
2
  dest->h_length = 0;
88
2
  dest->h_name = nullptr;
89
90
  /* copy `h_name` */
91
2
  size_t name_size = strlen(src->h_name) + 1;
92
2
  dest->h_name = node::Malloc<char>(name_size);
93
2
  memcpy(dest->h_name, src->h_name, name_size);
94
95
  /* copy `h_aliases` */
96
  size_t alias_count;
97
2
  for (alias_count = 0;
98
2
      src->h_aliases[alias_count] != nullptr;
99
      alias_count++) {
100
  }
101
102
2
  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
103
2
  for (size_t i = 0; i < alias_count; i++) {
104
    const size_t cur_alias_size = strlen(src->h_aliases[i]) + 1;
105
    dest->h_aliases[i] = node::Malloc(cur_alias_size);
106
    memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_size);
107
  }
108
2
  dest->h_aliases[alias_count] = nullptr;
109
110
  /* copy `h_addr_list` */
111
  size_t list_count;
112
4
  for (list_count = 0;
113
4
      src->h_addr_list[list_count] != nullptr;
114
      list_count++) {
115
  }
116
117
2
  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
118
4
  for (size_t i = 0; i < list_count; i++) {
119
2
    dest->h_addr_list[i] = node::Malloc(src->h_length);
120
2
    memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
121
  }
122
2
  dest->h_addr_list[list_count] = nullptr;
123
124
  /* work after work */
125
2
  dest->h_length = src->h_length;
126
2
  dest->h_addrtype = src->h_addrtype;
127
2
}
128
129
130
203
struct NodeAresTask final : public MemoryRetainer {
131
  ChannelWrap* channel;
132
  ares_socket_t sock;
133
  uv_poll_t poll_watcher;
134
135
  inline void MemoryInfo(MemoryTracker* trakcer) const override;
136
  SET_MEMORY_INFO_NAME(NodeAresTask)
137
  SET_SELF_SIZE(NodeAresTask)
138
139
1109
  struct Hash {
140
87
    inline size_t operator()(NodeAresTask* a) const {
141
87
      return std::hash<ares_socket_t>()(a->sock);
142
    }
143
  };
144
145
1109
  struct Equal {
146
29
    inline bool operator()(NodeAresTask* a, NodeAresTask* b) const {
147
29
      return a->sock == b->sock;
148
    }
149
  };
150
151
  static NodeAresTask* Create(ChannelWrap* channel, ares_socket_t sock);
152
153
  using List = std::unordered_set<NodeAresTask*, Hash, Equal>;
154
};
155
156
class ChannelWrap final : public AsyncWrap {
157
 public:
158
  ChannelWrap(Environment* env, v8::Local<v8::Object> object, int timeout);
159
  ~ChannelWrap() override;
160
161
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
162
163
  void Setup();
164
  void EnsureServers();
165
  void StartTimer();
166
  void CloseTimer();
167
168
  void ModifyActivityQueryCount(int count);
169
170
83
  inline uv_timer_t* timer_handle() { return timer_handle_; }
171
241
  inline ares_channel cares_channel() { return channel_; }
172
50
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
173
24
  inline void set_is_servers_default(bool is_default) {
174
24
    is_servers_default_ = is_default;
175
24
  }
176
28
  inline int active_query_count() { return active_query_count_; }
177
270
  inline NodeAresTask::List* task_list() { return &task_list_; }
178
179
  void MemoryInfo(MemoryTracker* tracker) const override;
180
4
  SET_MEMORY_INFO_NAME(ChannelWrap)
181
4
  SET_SELF_SIZE(ChannelWrap)
182
183
  static void AresTimeout(uv_timer_t* handle);
184
185
 private:
186
  uv_timer_t* timer_handle_ = nullptr;
187
  ares_channel channel_ = nullptr;
188
  bool query_last_ok_ = true;
189
  bool is_servers_default_ = true;
190
  bool library_inited_ = false;
191
  int timeout_;
192
  int active_query_count_ = 0;
193
  NodeAresTask::List task_list_;
194
};
195
196
10828
class GetAddrInfoReqWrap final : public ReqWrap<uv_getaddrinfo_t> {
197
 public:
198
  GetAddrInfoReqWrap(Environment* env,
199
                     v8::Local<v8::Object> req_wrap_obj,
200
                     bool verbatim);
201
202
1
  SET_NO_MEMORY_INFO()
203
1
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
204
1
  SET_SELF_SIZE(GetAddrInfoReqWrap)
205
206
5414
  bool verbatim() const { return verbatim_; }
207
208
 private:
209
  const bool verbatim_;
210
};
211
212
8
class GetNameInfoReqWrap final : public ReqWrap<uv_getnameinfo_t> {
213
 public:
214
  GetNameInfoReqWrap(Environment* env, v8::Local<v8::Object> req_wrap_obj);
215
216
1
  SET_NO_MEMORY_INFO()
217
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
218
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
219
};
220
221
100
struct ResponseData final {
222
  int status;
223
  bool is_host;
224
  SafeHostEntPointer host;
225
  MallocedBuffer<unsigned char> buf;
226
};
227
228
template <typename Traits>
229
class QueryWrap final : public AsyncWrap {
230
 public:
231
51
  QueryWrap(ChannelWrap* channel, v8::Local<v8::Object> req_wrap_obj)
232
      : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
233
        channel_(channel),
234
51
        trace_name_(Traits::name) {}
235
236
102
  ~QueryWrap() {
237






102
    CHECK_EQ(false, persistent().IsEmpty());
238
239
    // Let Callback() know that this object no longer exists.
240






51
    if (callback_ptr_ != nullptr)
241
1
      *callback_ptr_ = nullptr;
242
153
  }
243
244
51
  int Send(const char* name) {
245
51
    return Traits::Send(this, name);
246
  }
247
248
48
  void AresQuery(const char* name, int dnsclass, int type) {
249
48
    channel_->EnsureServers();
250






48
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
251
      TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
252
      "name", TRACE_STR_COPY(name));
253
48
    ares_query(
254






48
        channel_->cares_channel(),
255
48
        name,
256
        dnsclass,
257
        type,
258
        Callback,
259
        MakeCallbackPointer());
260
48
  }
261
262
33
  void ParseError(int status) {
263






33
    CHECK_NE(status, ARES_SUCCESS);
264
66
    v8::HandleScope handle_scope(env()->isolate());
265
33
    v8::Context::Scope context_scope(env()->context());
266
33
    const char* code = ToErrorCodeString(status);
267
33
    v8::Local<v8::Value> arg = OneByteString(env()->isolate(), code);
268






33
    TRACE_EVENT_NESTABLE_ASYNC_END1(
269
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
270
7
        "error", status);
271
40
    MakeCallback(env()->oncomplete_string(), 1, &arg);
272






66
  }
273
33
274
3
  const BaseObjectPtr<ChannelWrap>& channel() const { return channel_; }
275
276
50
  void AfterResponse() {
277






50
    CHECK(response_data_);
278
279
50
    int status = response_data_->status;
280
281






50
    if (status != ARES_SUCCESS)
282
31
      return ParseError(status);
283
284
19
    status = Traits::Parse(this, response_data_);
285
286






19
    if (status != ARES_SUCCESS)
287
2
      ParseError(status);
288
  }
289
290
51
  void* MakeCallbackPointer() {
291






51
    CHECK_NULL(callback_ptr_);
292
51
    callback_ptr_ = new QueryWrap<Traits>*(this);
293
51
    return callback_ptr_;
294
  }
295
296
51
  static QueryWrap<Traits>* FromCallbackPointer(void* arg) {
297
    std::unique_ptr<QueryWrap<Traits>*> wrap_ptr {
298
        static_cast<QueryWrap<Traits>**>(arg)
299
102
    };
300
51
    QueryWrap<Traits>* wrap = *wrap_ptr.get();
301






51
    if (wrap == nullptr) return nullptr;
302
50
    wrap->callback_ptr_ = nullptr;
303
50
    return wrap;
304
  }
305
306
48
  static void Callback(
307
      void* arg,
308
      int status,
309
      int timeouts,
310
      unsigned char* answer_buf,
311
      int answer_len) {
312
48
    QueryWrap<Traits>* wrap = FromCallbackPointer(arg);
313






48
    if (wrap == nullptr) return;
314
315
47
    unsigned char* buf_copy = nullptr;
316






47
    if (status == ARES_SUCCESS) {
317
17
      buf_copy = node::Malloc<unsigned char>(answer_len);
318
17
      memcpy(buf_copy, answer_buf, answer_len);
319
    }
320
321
47
    wrap->response_data_ = std::make_unique<ResponseData>();
322
47
    ResponseData* data = wrap->response_data_.get();
323
47
    data->status = status;
324
47
    data->is_host = false;
325
47
    data->buf = MallocedBuffer<unsigned char>(buf_copy, answer_len);
326
327
47
    wrap->QueueResponseCallback(status);
328
  }
329
330
3
  static void Callback(
331
      void* arg,
332
      int status,
333
      int timeouts,
334
      struct hostent* host) {
335
3
    QueryWrap<Traits>* wrap = FromCallbackPointer(arg);
336
3
    if (wrap == nullptr) return;
337
338
3
    struct hostent* host_copy = nullptr;
339
3
    if (status == ARES_SUCCESS) {
340
2
      host_copy = node::Malloc<hostent>(1);
341
2
      cares_wrap_hostent_cpy(host_copy, host);
342
    }
343
344
3
    wrap->response_data_ = std::make_unique<ResponseData>();
345
3
    ResponseData* data = wrap->response_data_.get();
346
3
    data->status = status;
347
3
    data->host.reset(host_copy);
348
3
    data->is_host = true;
349
350
3
    wrap->QueueResponseCallback(status);
351
  }
352
353
50
  void QueueResponseCallback(int status) {
354
100
    BaseObjectPtr<QueryWrap<Traits>> strong_ref{this};
355
300
    env()->SetImmediate([this, strong_ref](Environment*) {
356
50
      AfterResponse();
357
358
      // Delete once strong_ref goes out of scope.
359
50
      Detach();
360
50
    });
361
362
50
    channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
363
50
    channel_->ModifyActivityQueryCount(-1);
364
50
  }
365
366
17
  void CallOnComplete(
367
      v8::Local<v8::Value> answer,
368
      v8::Local<v8::Value> extra = v8::Local<v8::Value>()) {
369
34
    v8::HandleScope handle_scope(env()->isolate());
370
17
    v8::Context::Scope context_scope(env()->context());
371
    v8::Local<v8::Value> argv[] = {
372
      v8::Integer::New(env()->isolate(), 0),
373
      answer,
374
      extra
375
34
    };
376
34
    const int argc = arraysize(argv) - extra.IsEmpty();
377






17
    TRACE_EVENT_NESTABLE_ASYNC_END0(
378
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
379
9
380
26
    MakeCallback(env()->oncomplete_string(), argc, argv);
381






34
  }
382
17
383
1
  void MemoryInfo(MemoryTracker* tracker) const override {
384
1
    tracker->TrackField("channel", channel_);
385






1
    if (response_data_) {
386
1
      tracker->TrackFieldWithSize("response", response_data_->buf.size);
387
    }
388
1
  }
389
390
1
  SET_MEMORY_INFO_NAME(QueryWrap)
391
1
  SET_SELF_SIZE(QueryWrap<Traits>)
392
393
 private:
394
  BaseObjectPtr<ChannelWrap> channel_;
395
396
  std::unique_ptr<ResponseData> response_data_;
397
  const char* trace_name_;
398
  // Pointer to pointer to 'this' that can be reset from the destructor,
399
  // in order to let Callback() know that 'this' no longer exists.
400
  QueryWrap<Traits>** callback_ptr_ = nullptr;
401
};
402
403
struct AnyTraits final {
404
  static constexpr const char* name = "resolveAny";
405
  static int Send(QueryWrap<AnyTraits>* wrap, const char* name);
406
  static int Parse(
407
      QueryWrap<AnyTraits>* wrap,
408
      const std::unique_ptr<ResponseData>& response);
409
};
410
411
struct ATraits final {
412
  static constexpr const char* name = "resolve4";
413
  static int Send(QueryWrap<ATraits>* wrap, const char* name);
414
  static int Parse(
415
      QueryWrap<ATraits>* wrap,
416
      const std::unique_ptr<ResponseData>& response);
417
};
418
419
struct AaaaTraits final {
420
  static constexpr const char* name = "resolve6";
421
  static int Send(QueryWrap<AaaaTraits>* wrap, const char* name);
422
  static int Parse(
423
      QueryWrap<AaaaTraits>* wrap,
424
      const std::unique_ptr<ResponseData>& response);
425
};
426
427
struct CaaTraits final {
428
  static constexpr const char* name = "resolveCaa";
429
  static int Send(QueryWrap<CaaTraits>* wrap, const char* name);
430
  static int Parse(
431
      QueryWrap<CaaTraits>* wrap,
432
      const std::unique_ptr<ResponseData>& response);
433
};
434
435
struct CnameTraits final {
436
  static constexpr const char* name = "resolveCname";
437
  static int Send(QueryWrap<CnameTraits>* wrap, const char* name);
438
  static int Parse(
439
      QueryWrap<CnameTraits>* wrap,
440
      const std::unique_ptr<ResponseData>& response);
441
};
442
443
struct MxTraits final {
444
  static constexpr const char* name = "resolveMx";
445
  static int Send(QueryWrap<MxTraits>* wrap, const char* name);
446
  static int Parse(
447
      QueryWrap<MxTraits>* wrap,
448
      const std::unique_ptr<ResponseData>& response);
449
};
450
451
struct NsTraits final {
452
  static constexpr const char* name = "resolveNs";
453
  static int Send(QueryWrap<NsTraits>* wrap, const char* name);
454
  static int Parse(
455
      QueryWrap<NsTraits>* wrap,
456
      const std::unique_ptr<ResponseData>& response);
457
};
458
459
struct TxtTraits final {
460
  static constexpr const char* name = "resolveTxt";
461
  static int Send(QueryWrap<TxtTraits>* wrap, const char* name);
462
  static int Parse(
463
      QueryWrap<TxtTraits>* wrap,
464
      const std::unique_ptr<ResponseData>& response);
465
};
466
467
struct SrvTraits final {
468
  static constexpr const char* name = "resolveSrv";
469
  static int Send(QueryWrap<SrvTraits>* wrap, const char* name);
470
  static int Parse(
471
      QueryWrap<SrvTraits>* wrap,
472
      const std::unique_ptr<ResponseData>& response);
473
};
474
475
struct PtrTraits final {
476
  static constexpr const char* name = "resolvePtr";
477
  static int Send(QueryWrap<PtrTraits>* wrap, const char* name);
478
  static int Parse(
479
      QueryWrap<PtrTraits>* wrap,
480
      const std::unique_ptr<ResponseData>& response);
481
};
482
483
struct NaptrTraits final {
484
  static constexpr const char* name = "resolveNaptr";
485
  static int Send(QueryWrap<NaptrTraits>* wrap, const char* name);
486
  static int Parse(
487
      QueryWrap<NaptrTraits>* wrap,
488
      const std::unique_ptr<ResponseData>& response);
489
};
490
491
struct SoaTraits final {
492
  static constexpr const char* name = "resolveSoa";
493
  static int Send(QueryWrap<SoaTraits>* wrap, const char* name);
494
  static int Parse(
495
      QueryWrap<SoaTraits>* wrap,
496
      const std::unique_ptr<ResponseData>& response);
497
};
498
499
struct ReverseTraits final {
500
  static constexpr const char* name = "reverse";
501
  static int Send(QueryWrap<ReverseTraits>* wrap, const char* name);
502
  static int Parse(
503
      QueryWrap<ReverseTraits>* wrap,
504
      const std::unique_ptr<ResponseData>& response);
505
};
506
507
using QueryAnyWrap = QueryWrap<AnyTraits>;
508
using QueryAWrap = QueryWrap<ATraits>;
509
using QueryAaaaWrap = QueryWrap<AaaaTraits>;
510
using QueryCaaWrap = QueryWrap<CaaTraits>;
511
using QueryCnameWrap = QueryWrap<CnameTraits>;
512
using QueryMxWrap = QueryWrap<MxTraits>;
513
using QueryNsWrap = QueryWrap<NsTraits>;
514
using QueryTxtWrap = QueryWrap<TxtTraits>;
515
using QuerySrvWrap = QueryWrap<SrvTraits>;
516
using QueryPtrWrap = QueryWrap<PtrTraits>;
517
using QueryNaptrWrap = QueryWrap<NaptrTraits>;
518
using QuerySoaWrap = QueryWrap<SoaTraits>;
519
using GetHostByAddrWrap = QueryWrap<ReverseTraits>;
520
521
}  // namespace cares_wrap
522
}  // namespace node
523
524
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
525
526
#endif  // SRC_CARES_WRAP_H_