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-04-27 04:12:29 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
#ifndef T_CAA
36
#  define T_CAA    257 /* Certification Authority Authorization */
37
#endif
38
39
#if defined(__OpenBSD__)
40
# define AI_V4MAPPED 0
41
#endif
42
43
namespace node {
44
namespace cares_wrap {
45
46
constexpr int ns_t_cname_or_a = -1;
47
constexpr int DNS_ESETSRVPENDING = -1000;
48
49
class ChannelWrap;
50
51
inline void safe_free_hostent(struct hostent* host);
52
53
using HostEntPointer = DeleteFnPtr<hostent, ares_free_hostent>;
54
using SafeHostEntPointer = DeleteFnPtr<hostent, safe_free_hostent>;
55
56
33
inline const char* ToErrorCodeString(int status) {
57






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






102
    CHECK_EQ(false, persistent().IsEmpty());
246
247
    // Let Callback() know that this object no longer exists.
248






51
    if (callback_ptr_ != nullptr)
249
1
      *callback_ptr_ = nullptr;
250
153
  }
251
252
51
  int Send(const char* name) {
253
51
    return Traits::Send(this, name);
254
  }
255
256
48
  void AresQuery(const char* name, int dnsclass, int type) {
257
48
    channel_->EnsureServers();
258






48
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
259
      TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
260
      "name", TRACE_STR_COPY(name));
261
48
    ares_query(
262






48
        channel_->cares_channel(),
263
48
        name,
264
        dnsclass,
265
        type,
266
        Callback,
267
        MakeCallbackPointer());
268
48
  }
269
270
33
  void ParseError(int status) {
271






33
    CHECK_NE(status, ARES_SUCCESS);
272
66
    v8::HandleScope handle_scope(env()->isolate());
273
33
    v8::Context::Scope context_scope(env()->context());
274
33
    const char* code = ToErrorCodeString(status);
275
33
    v8::Local<v8::Value> arg = OneByteString(env()->isolate(), code);
276






33
    TRACE_EVENT_NESTABLE_ASYNC_END1(
277
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
278
7
        "error", status);
279
40
    MakeCallback(env()->oncomplete_string(), 1, &arg);
280






66
  }
281
33
282
3
  const BaseObjectPtr<ChannelWrap>& channel() const { return channel_; }
283
284
50
  void AfterResponse() {
285






50
    CHECK(response_data_);
286
287
50
    int status = response_data_->status;
288
289






50
    if (status != ARES_SUCCESS)
290
31
      return ParseError(status);
291
292
19
    status = Traits::Parse(this, response_data_);
293
294






19
    if (status != ARES_SUCCESS)
295
2
      ParseError(status);
296
  }
297
298
51
  void* MakeCallbackPointer() {
299






51
    CHECK_NULL(callback_ptr_);
300
51
    callback_ptr_ = new QueryWrap<Traits>*(this);
301
51
    return callback_ptr_;
302
  }
303
304
51
  static QueryWrap<Traits>* FromCallbackPointer(void* arg) {
305
    std::unique_ptr<QueryWrap<Traits>*> wrap_ptr {
306
        static_cast<QueryWrap<Traits>**>(arg)
307
102
    };
308
51
    QueryWrap<Traits>* wrap = *wrap_ptr.get();
309






51
    if (wrap == nullptr) return nullptr;
310
50
    wrap->callback_ptr_ = nullptr;
311
50
    return wrap;
312
  }
313
314
48
  static void Callback(
315
      void* arg,
316
      int status,
317
      int timeouts,
318
      unsigned char* answer_buf,
319
      int answer_len) {
320
48
    QueryWrap<Traits>* wrap = FromCallbackPointer(arg);
321






48
    if (wrap == nullptr) return;
322
323
47
    unsigned char* buf_copy = nullptr;
324






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






17
    TRACE_EVENT_NESTABLE_ASYNC_END0(
386
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
387
9
388
26
    MakeCallback(env()->oncomplete_string(), argc, argv);
389






34
  }
390
17
391
1
  void MemoryInfo(MemoryTracker* tracker) const override {
392
1
    tracker->TrackField("channel", channel_);
393






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