GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_report_utils.cc Lines: 157 181 86.7 %
Date: 2022-12-07 04:23:16 Branches: 65 94 69.1 %

Line Branch Exec Source
1
#include "json_utils.h"
2
#include "node_internals.h"
3
#include "node_report.h"
4
#include "util-inl.h"
5
6
namespace node {
7
namespace report {
8
9
static constexpr auto null = JSONWriter::Null{};
10
11
// Utility function to format socket information.
12
16
static void ReportEndpoint(uv_handle_t* h,
13
                           struct sockaddr* addr,
14
                           const char* name,
15
                           JSONWriter* writer) {
16
16
  if (addr == nullptr) {
17
3
    writer->json_keyvalue(name, null);
18
3
    return;
19
  }
20
21
  uv_getnameinfo_t endpoint;
22
13
  char* host = nullptr;
23
  char hostbuf[INET6_ADDRSTRLEN];
24
13
  const int family = addr->sa_family;
25
13
  const int port = ntohs(family == AF_INET ?
26
5
                         reinterpret_cast<sockaddr_in*>(addr)->sin_port :
27
8
                         reinterpret_cast<sockaddr_in6*>(addr)->sin6_port);
28
29
13
  if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) {
30
13
    host = endpoint.host;
31
    DCHECK_EQ(port, std::stoi(endpoint.service));
32
  } else {
33
    const void* src = family == AF_INET ?
34
                      static_cast<void*>(
35
                        &(reinterpret_cast<sockaddr_in*>(addr)->sin_addr)) :
36
                      static_cast<void*>(
37
                        &(reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr));
38
    if (uv_inet_ntop(family, src, hostbuf, sizeof(hostbuf)) == 0) {
39
      host = hostbuf;
40
    }
41
  }
42
13
  writer->json_objectstart(name);
43
13
  if (host != nullptr) {
44
13
    writer->json_keyvalue("host", host);
45
  }
46
13
  writer->json_keyvalue("port", port);
47
13
  writer->json_objectend();
48
}
49
50
// Utility function to format libuv socket information.
51
8
static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
52
  struct sockaddr_storage addr_storage;
53
8
  struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
54
8
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
55
8
  int addr_size = sizeof(addr_storage);
56
8
  int rc = -1;
57
58
8
  switch (h->type) {
59
2
    case UV_UDP:
60
2
      rc = uv_udp_getsockname(&handle->udp, addr, &addr_size);
61
2
      break;
62
6
    case UV_TCP:
63
6
      rc = uv_tcp_getsockname(&handle->tcp, addr, &addr_size);
64
6
      break;
65
    default:
66
      break;
67
  }
68
8
  ReportEndpoint(h, rc == 0 ? addr : nullptr,  "localEndpoint", writer);
69
70
8
  switch (h->type) {
71
2
    case UV_UDP:
72
2
      rc = uv_udp_getpeername(&handle->udp, addr, &addr_size);
73
2
      break;
74
6
    case UV_TCP:
75
6
      rc = uv_tcp_getpeername(&handle->tcp, addr, &addr_size);
76
6
      break;
77
    default:
78
      break;
79
  }
80
8
  ReportEndpoint(h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer);
81
8
}
82
83
// Utility function to format libuv pipe information.
84
12
static void ReportPipeEndpoints(uv_handle_t* h, JSONWriter* writer) {
85
12
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
86
24
  MallocedBuffer<char> buffer(0);
87
12
  size_t buffer_size = 0;
88
12
  int rc = -1;
89
90
  // First call to get required buffer size.
91
12
  rc = uv_pipe_getsockname(&handle->pipe, buffer.data, &buffer_size);
92
12
  if (rc == UV_ENOBUFS) {
93
12
    buffer = MallocedBuffer<char>(buffer_size);
94
12
    if (buffer.data != nullptr) {
95
12
      rc = uv_pipe_getsockname(&handle->pipe, buffer.data, &buffer_size);
96
    } else {
97
      buffer_size = 0;
98
    }
99
  }
100

12
  if (rc == 0 && buffer_size != 0 && buffer.data != nullptr) {
101
2
    writer->json_keyvalue("localEndpoint", buffer.data);
102
  } else {
103
10
    writer->json_keyvalue("localEndpoint", null);
104
  }
105
106
  // First call to get required buffer size.
107
12
  rc = uv_pipe_getpeername(&handle->pipe, buffer.data, &buffer_size);
108
12
  if (rc == UV_ENOBUFS) {
109
10
    buffer = MallocedBuffer<char>(buffer_size);
110
10
    if (buffer.data != nullptr) {
111
10
      rc = uv_pipe_getpeername(&handle->pipe, buffer.data, &buffer_size);
112
    }
113
  }
114

12
  if (rc == 0 && buffer_size != 0 && buffer.data != nullptr) {
115
1
    writer->json_keyvalue("remoteEndpoint", buffer.data);
116
  } else {
117
11
    writer->json_keyvalue("remoteEndpoint", null);
118
  }
119
12
}
120
121
// Utility function to format libuv path information.
122
2
static void ReportPath(uv_handle_t* h, JSONWriter* writer) {
123
4
  MallocedBuffer<char> buffer(0);
124
2
  int rc = -1;
125
2
  size_t size = 0;
126
2
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
127
2
  bool wrote_filename = false;
128
  // First call to get required buffer size.
129
2
  switch (h->type) {
130
1
    case UV_FS_EVENT:
131
1
      rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
132
1
      break;
133
1
    case UV_FS_POLL:
134
1
      rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
135
1
      break;
136
    default:
137
      break;
138
  }
139
2
  if (rc == UV_ENOBUFS) {
140
2
    buffer = MallocedBuffer<char>(size + 1);
141
2
    switch (h->type) {
142
1
      case UV_FS_EVENT:
143
1
        rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
144
1
        break;
145
1
      case UV_FS_POLL:
146
1
        rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
147
1
        break;
148
      default:
149
        break;
150
    }
151
2
    if (rc == 0) {
152
      // buffer is not null terminated.
153
2
      buffer.data[size] = '\0';
154
2
      writer->json_keyvalue("filename", buffer.data);
155
2
      wrote_filename = true;
156
    }
157
  }
158
2
  if (!wrote_filename) writer->json_keyvalue("filename", null);
159
2
}
160
161
// Utility function to walk libuv handles.
162
273
void WalkHandle(uv_handle_t* h, void* arg) {
163
273
  const char* type = uv_handle_type_name(h->type);
164
273
  JSONWriter* writer = static_cast<JSONWriter*>(arg);
165
273
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
166
167
273
  writer->json_start();
168
273
  writer->json_keyvalue("type", type);
169
273
  writer->json_keyvalue("is_active", static_cast<bool>(uv_is_active(h)));
170
273
  writer->json_keyvalue("is_referenced", static_cast<bool>(uv_has_ref(h)));
171
273
  writer->json_keyvalue("address",
172
546
                        ValueToHexString(reinterpret_cast<uint64_t>(h)));
173
174


273
  switch (h->type) {
175
2
    case UV_FS_EVENT:
176
    case UV_FS_POLL:
177
2
      ReportPath(h, writer);
178
2
      break;
179
1
    case UV_PROCESS:
180
1
      writer->json_keyvalue("pid", handle->process.pid);
181
1
      break;
182
8
    case UV_TCP:
183
    case UV_UDP:
184
8
      ReportEndpoints(h, writer);
185
8
      break;
186
12
    case UV_NAMED_PIPE:
187
12
      ReportPipeEndpoints(h, writer);
188
12
      break;
189
37
    case UV_TIMER: {
190
37
      uint64_t due = handle->timer.timeout;
191
37
      uint64_t now = uv_now(handle->timer.loop);
192
37
      writer->json_keyvalue("repeat", uv_timer_get_repeat(&handle->timer));
193
37
      writer->json_keyvalue("firesInMsFromNow",
194
37
                            static_cast<int64_t>(due - now));
195
37
      writer->json_keyvalue("expired", now >= due);
196
37
      break;
197
    }
198
    case UV_TTY: {
199
      int height, width, rc;
200
      rc = uv_tty_get_winsize(&(handle->tty), &width, &height);
201
      if (rc == 0) {
202
        writer->json_keyvalue("width", width);
203
        writer->json_keyvalue("height", height);
204
      }
205
      break;
206
    }
207
1
    case UV_SIGNAL:
208
      // SIGWINCH is used by libuv so always appears.
209
      // See http://docs.libuv.org/en/v1.x/signal.html
210
1
      writer->json_keyvalue("signum", handle->signal.signum);
211
1
      writer->json_keyvalue("signal", signo_string(handle->signal.signum));
212
1
      break;
213
212
    default:
214
212
      break;
215
  }
216
217

273
  if (h->type == UV_TCP || h->type == UV_UDP
218
#ifndef _WIN32
219
265
      || h->type == UV_NAMED_PIPE
220
#endif
221
  ) {
222
    // These *must* be 0 or libuv will set the buffer sizes to the non-zero
223
    // values they contain.
224
20
    int send_size = 0;
225
20
    int recv_size = 0;
226
20
    uv_send_buffer_size(h, &send_size);
227
20
    uv_recv_buffer_size(h, &recv_size);
228
20
    writer->json_keyvalue("sendBufferSize", send_size);
229
20
    writer->json_keyvalue("recvBufferSize", recv_size);
230
  }
231
232
#ifndef _WIN32
233

273
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY ||
234

255
      h->type == UV_UDP || h->type == UV_POLL) {
235
    uv_os_fd_t fd_v;
236
20
    int rc = uv_fileno(h, &fd_v);
237
238
20
    if (rc == 0) {
239
20
      writer->json_keyvalue("fd", static_cast<int>(fd_v));
240

20
      switch (fd_v) {
241
        case STDIN_FILENO:
242
          writer->json_keyvalue("stdio", "stdin");
243
          break;
244
        case STDOUT_FILENO:
245
          writer->json_keyvalue("stdio", "stdout");
246
          break;
247
5
        case STDERR_FILENO:
248
5
          writer->json_keyvalue("stdio", "stderr");
249
5
          break;
250
15
        default:
251
15
          break;
252
      }
253
    }
254
  }
255
#endif
256
257

273
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY) {
258
18
    writer->json_keyvalue("writeQueueSize", handle->stream.write_queue_size);
259
18
    writer->json_keyvalue("readable",
260
18
                          static_cast<bool>(uv_is_readable(&handle->stream)));
261
18
    writer->json_keyvalue("writable",
262
18
                          static_cast<bool>(uv_is_writable(&handle->stream)));
263
  }
264
273
  if (h->type == UV_UDP) {
265
2
    writer->json_keyvalue(
266
        "writeQueueSize",
267
2
        uv_udp_get_send_queue_size(reinterpret_cast<uv_udp_t*>(h)));
268
2
    writer->json_keyvalue(
269
        "writeQueueCount",
270
2
        uv_udp_get_send_queue_count(reinterpret_cast<uv_udp_t*>(h)));
271
  }
272
273
  writer->json_end();
273
273
}
274
275
}  // namespace report
276
}  // namespace node