GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 report { |
||
7 |
|||
8 |
using node::JSONWriter; |
||
9 |
using node::MallocedBuffer; |
||
10 |
|||
11 |
static constexpr auto null = JSONWriter::Null{}; |
||
12 |
|||
13 |
// Utility function to format socket information. |
||
14 |
10 |
static void ReportEndpoint(uv_handle_t* h, |
|
15 |
struct sockaddr* addr, |
||
16 |
const char* name, |
||
17 |
JSONWriter* writer) { |
||
18 |
✓✓ | 10 |
if (addr == nullptr) { |
19 |
2 |
writer->json_keyvalue(name, null); |
|
20 |
2 |
return; |
|
21 |
} |
||
22 |
|||
23 |
uv_getnameinfo_t endpoint; |
||
24 |
8 |
char* host = nullptr; |
|
25 |
char hostbuf[INET6_ADDRSTRLEN]; |
||
26 |
8 |
const int family = addr->sa_family; |
|
27 |
✓✓ | 8 |
const int port = ntohs(family == AF_INET ? |
28 |
3 |
reinterpret_cast<sockaddr_in*>(addr)->sin_port : |
|
29 |
5 |
reinterpret_cast<sockaddr_in6*>(addr)->sin6_port); |
|
30 |
|||
31 |
✓✗ | 8 |
if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) { |
32 |
8 |
host = endpoint.host; |
|
33 |
DCHECK_EQ(port, std::stoi(endpoint.service)); |
||
34 |
} else { |
||
35 |
const void* src = family == AF_INET ? |
||
36 |
static_cast<void*>( |
||
37 |
&(reinterpret_cast<sockaddr_in*>(addr)->sin_addr)) : |
||
38 |
static_cast<void*>( |
||
39 |
&(reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr)); |
||
40 |
if (uv_inet_ntop(family, src, hostbuf, sizeof(hostbuf)) == 0) { |
||
41 |
host = hostbuf; |
||
42 |
} |
||
43 |
} |
||
44 |
8 |
writer->json_objectstart(name); |
|
45 |
✓✗ | 8 |
if (host != nullptr) { |
46 |
8 |
writer->json_keyvalue("host", host); |
|
47 |
} |
||
48 |
8 |
writer->json_keyvalue("port", port); |
|
49 |
8 |
writer->json_objectend(); |
|
50 |
} |
||
51 |
|||
52 |
// Utility function to format libuv socket information. |
||
53 |
5 |
static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) { |
|
54 |
struct sockaddr_storage addr_storage; |
||
55 |
5 |
struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); |
|
56 |
5 |
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h); |
|
57 |
5 |
int addr_size = sizeof(addr_storage); |
|
58 |
5 |
int rc = -1; |
|
59 |
|||
60 |
✓✓✗ | 5 |
switch (h->type) { |
61 |
2 |
case UV_UDP: |
|
62 |
2 |
rc = uv_udp_getsockname(&handle->udp, addr, &addr_size); |
|
63 |
2 |
break; |
|
64 |
3 |
case UV_TCP: |
|
65 |
3 |
rc = uv_tcp_getsockname(&handle->tcp, addr, &addr_size); |
|
66 |
3 |
break; |
|
67 |
default: |
||
68 |
break; |
||
69 |
} |
||
70 |
✓✗ | 5 |
ReportEndpoint(h, rc == 0 ? addr : nullptr, "localEndpoint", writer); |
71 |
|||
72 |
✓✓✗ | 5 |
switch (h->type) { |
73 |
2 |
case UV_UDP: |
|
74 |
2 |
rc = uv_udp_getpeername(&handle->udp, addr, &addr_size); |
|
75 |
2 |
break; |
|
76 |
3 |
case UV_TCP: |
|
77 |
3 |
rc = uv_tcp_getpeername(&handle->tcp, addr, &addr_size); |
|
78 |
3 |
break; |
|
79 |
default: |
||
80 |
break; |
||
81 |
} |
||
82 |
✓✓ | 5 |
ReportEndpoint(h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer); |
83 |
5 |
} |
|
84 |
|||
85 |
// Utility function to format libuv pipe information. |
||
86 |
7 |
static void ReportPipeEndpoints(uv_handle_t* h, JSONWriter* writer) { |
|
87 |
7 |
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h); |
|
88 |
14 |
MallocedBuffer<char> buffer(0); |
|
89 |
7 |
size_t buffer_size = 0; |
|
90 |
7 |
int rc = -1; |
|
91 |
|||
92 |
// First call to get required buffer size. |
||
93 |
7 |
rc = uv_pipe_getsockname(&handle->pipe, buffer.data, &buffer_size); |
|
94 |
✓✗ | 7 |
if (rc == UV_ENOBUFS) { |
95 |
7 |
buffer = MallocedBuffer<char>(buffer_size); |
|
96 |
✓✗ | 7 |
if (buffer.data != nullptr) { |
97 |
7 |
rc = uv_pipe_getsockname(&handle->pipe, buffer.data, &buffer_size); |
|
98 |
} else { |
||
99 |
buffer_size = 0; |
||
100 |
} |
||
101 |
} |
||
102 |
✓✗✓✓ ✓✗ |
7 |
if (rc == 0 && buffer_size != 0 && buffer.data != nullptr) { |
103 |
2 |
writer->json_keyvalue("localEndpoint", buffer.data); |
|
104 |
} else { |
||
105 |
5 |
writer->json_keyvalue("localEndpoint", null); |
|
106 |
} |
||
107 |
|||
108 |
// First call to get required buffer size. |
||
109 |
7 |
rc = uv_pipe_getpeername(&handle->pipe, buffer.data, &buffer_size); |
|
110 |
✓✓ | 7 |
if (rc == UV_ENOBUFS) { |
111 |
5 |
buffer = MallocedBuffer<char>(buffer_size); |
|
112 |
✓✗ | 5 |
if (buffer.data != nullptr) { |
113 |
5 |
rc = uv_pipe_getpeername(&handle->pipe, buffer.data, &buffer_size); |
|
114 |
} |
||
115 |
} |
||
116 |
✓✓✓✓ ✓✗ |
7 |
if (rc == 0 && buffer_size != 0 && buffer.data != nullptr) { |
117 |
1 |
writer->json_keyvalue("remoteEndpoint", buffer.data); |
|
118 |
} else { |
||
119 |
6 |
writer->json_keyvalue("remoteEndpoint", null); |
|
120 |
} |
||
121 |
7 |
} |
|
122 |
|||
123 |
// Utility function to format libuv path information. |
||
124 |
2 |
static void ReportPath(uv_handle_t* h, JSONWriter* writer) { |
|
125 |
4 |
MallocedBuffer<char> buffer(0); |
|
126 |
2 |
int rc = -1; |
|
127 |
2 |
size_t size = 0; |
|
128 |
2 |
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h); |
|
129 |
2 |
bool wrote_filename = false; |
|
130 |
// First call to get required buffer size. |
||
131 |
✓✓✗ | 2 |
switch (h->type) { |
132 |
1 |
case UV_FS_EVENT: |
|
133 |
1 |
rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size); |
|
134 |
1 |
break; |
|
135 |
1 |
case UV_FS_POLL: |
|
136 |
1 |
rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size); |
|
137 |
1 |
break; |
|
138 |
default: |
||
139 |
break; |
||
140 |
} |
||
141 |
✓✗ | 2 |
if (rc == UV_ENOBUFS) { |
142 |
2 |
buffer = MallocedBuffer<char>(size + 1); |
|
143 |
✓✓✗ | 2 |
switch (h->type) { |
144 |
1 |
case UV_FS_EVENT: |
|
145 |
1 |
rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size); |
|
146 |
1 |
break; |
|
147 |
1 |
case UV_FS_POLL: |
|
148 |
1 |
rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size); |
|
149 |
1 |
break; |
|
150 |
default: |
||
151 |
break; |
||
152 |
} |
||
153 |
✓✗ | 2 |
if (rc == 0) { |
154 |
// buffer is not null terminated. |
||
155 |
2 |
buffer.data[size] = '\0'; |
|
156 |
2 |
writer->json_keyvalue("filename", buffer.data); |
|
157 |
2 |
wrote_filename = true; |
|
158 |
} |
||
159 |
} |
||
160 |
✗✓ | 2 |
if (!wrote_filename) writer->json_keyvalue("filename", null); |
161 |
2 |
} |
|
162 |
|||
163 |
// Utility function to walk libuv handles. |
||
164 |
220 |
void WalkHandle(uv_handle_t* h, void* arg) { |
|
165 |
220 |
const char* type = uv_handle_type_name(h->type); |
|
166 |
220 |
JSONWriter* writer = static_cast<JSONWriter*>(arg); |
|
167 |
220 |
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h); |
|
168 |
|||
169 |
220 |
writer->json_start(); |
|
170 |
220 |
writer->json_keyvalue("type", type); |
|
171 |
220 |
writer->json_keyvalue("is_active", static_cast<bool>(uv_is_active(h))); |
|
172 |
220 |
writer->json_keyvalue("is_referenced", static_cast<bool>(uv_has_ref(h))); |
|
173 |
220 |
writer->json_keyvalue("address", |
|
174 |
440 |
ValueToHexString(reinterpret_cast<uint64_t>(h))); |
|
175 |
|||
176 |
✓✓✓✓ ✓✗✓✓ |
220 |
switch (h->type) { |
177 |
2 |
case UV_FS_EVENT: |
|
178 |
case UV_FS_POLL: |
||
179 |
2 |
ReportPath(h, writer); |
|
180 |
2 |
break; |
|
181 |
1 |
case UV_PROCESS: |
|
182 |
1 |
writer->json_keyvalue("pid", handle->process.pid); |
|
183 |
1 |
break; |
|
184 |
5 |
case UV_TCP: |
|
185 |
case UV_UDP: |
||
186 |
5 |
ReportEndpoints(h, writer); |
|
187 |
5 |
break; |
|
188 |
7 |
case UV_NAMED_PIPE: |
|
189 |
7 |
ReportPipeEndpoints(h, writer); |
|
190 |
7 |
break; |
|
191 |
30 |
case UV_TIMER: { |
|
192 |
30 |
uint64_t due = handle->timer.timeout; |
|
193 |
30 |
uint64_t now = uv_now(handle->timer.loop); |
|
194 |
30 |
writer->json_keyvalue("repeat", uv_timer_get_repeat(&handle->timer)); |
|
195 |
30 |
writer->json_keyvalue("firesInMsFromNow", |
|
196 |
30 |
static_cast<int64_t>(due - now)); |
|
197 |
30 |
writer->json_keyvalue("expired", now >= due); |
|
198 |
30 |
break; |
|
199 |
} |
||
200 |
case UV_TTY: { |
||
201 |
int height, width, rc; |
||
202 |
rc = uv_tty_get_winsize(&(handle->tty), &width, &height); |
||
203 |
if (rc == 0) { |
||
204 |
writer->json_keyvalue("width", width); |
||
205 |
writer->json_keyvalue("height", height); |
||
206 |
} |
||
207 |
break; |
||
208 |
} |
||
209 |
1 |
case UV_SIGNAL: |
|
210 |
// SIGWINCH is used by libuv so always appears. |
||
211 |
// See http://docs.libuv.org/en/v1.x/signal.html |
||
212 |
1 |
writer->json_keyvalue("signum", handle->signal.signum); |
|
213 |
1 |
writer->json_keyvalue("signal", |
|
214 |
1 |
node::signo_string(handle->signal.signum)); |
|
215 |
1 |
break; |
|
216 |
174 |
default: |
|
217 |
174 |
break; |
|
218 |
} |
||
219 |
|||
220 |
✓✓✓✓ |
220 |
if (h->type == UV_TCP || h->type == UV_UDP |
221 |
#ifndef _WIN32 |
||
222 |
✓✓ | 215 |
|| h->type == UV_NAMED_PIPE |
223 |
#endif |
||
224 |
) { |
||
225 |
// These *must* be 0 or libuv will set the buffer sizes to the non-zero |
||
226 |
// values they contain. |
||
227 |
12 |
int send_size = 0; |
|
228 |
12 |
int recv_size = 0; |
|
229 |
12 |
uv_send_buffer_size(h, &send_size); |
|
230 |
12 |
uv_recv_buffer_size(h, &recv_size); |
|
231 |
12 |
writer->json_keyvalue("sendBufferSize", send_size); |
|
232 |
12 |
writer->json_keyvalue("recvBufferSize", recv_size); |
|
233 |
} |
||
234 |
|||
235 |
#ifndef _WIN32 |
||
236 |
✓✓✓✓ ✓✗ |
220 |
if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY || |
237 |
✓✓✗✓ |
210 |
h->type == UV_UDP || h->type == UV_POLL) { |
238 |
uv_os_fd_t fd_v; |
||
239 |
12 |
int rc = uv_fileno(h, &fd_v); |
|
240 |
|||
241 |
✓✗ | 12 |
if (rc == 0) { |
242 |
12 |
writer->json_keyvalue("fd", static_cast<int>(fd_v)); |
|
243 |
✗✗✗✓ |
12 |
switch (fd_v) { |
244 |
case STDIN_FILENO: |
||
245 |
writer->json_keyvalue("stdio", "stdin"); |
||
246 |
break; |
||
247 |
case STDOUT_FILENO: |
||
248 |
writer->json_keyvalue("stdio", "stdout"); |
||
249 |
break; |
||
250 |
case STDERR_FILENO: |
||
251 |
writer->json_keyvalue("stdio", "stderr"); |
||
252 |
break; |
||
253 |
12 |
default: |
|
254 |
12 |
break; |
|
255 |
} |
||
256 |
} |
||
257 |
} |
||
258 |
#endif |
||
259 |
|||
260 |
✓✓✓✓ ✗✓ |
220 |
if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY) { |
261 |
10 |
writer->json_keyvalue("writeQueueSize", handle->stream.write_queue_size); |
|
262 |
10 |
writer->json_keyvalue("readable", |
|
263 |
10 |
static_cast<bool>(uv_is_readable(&handle->stream))); |
|
264 |
10 |
writer->json_keyvalue("writable", |
|
265 |
10 |
static_cast<bool>(uv_is_writable(&handle->stream))); |
|
266 |
} |
||
267 |
|||
268 |
220 |
writer->json_end(); |
|
269 |
220 |
} |
|
270 |
|||
271 |
} // namespace report |
Generated by: GCOVR (Version 4.2) |