| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 06d592c commit b62e228
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,15 +7,52 @@ using node::MallocedBuffer; | |||
| 7 | 7 | ||
| 8 | 8 | static constexpr auto null = JSONWriter::Null{}; | |
| 9 | 9 | ||
| 10 | + // Utility function to format socket information. | ||
| 11 | + static void ReportEndpoint(uv_handle_t* h, | ||
| 12 | + struct sockaddr* addr, | ||
| 13 | + const char* name, | ||
| 14 | + JSONWriter* writer) { | ||
| 15 | + if (addr == nullptr) { | ||
| 16 | + writer->json_keyvalue(name, null); | ||
| 17 | + return; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + uv_getnameinfo_t endpoint; | ||
| 21 | + char* host = nullptr; | ||
| 22 | + char hostbuf[INET6_ADDRSTRLEN]; | ||
| 23 | + const int family = addr->sa_family; | ||
| 24 | + const int port = ntohs(family == AF_INET ? | ||
| 25 | + reinterpret_cast<sockaddr_in*>(addr)->sin_port : | ||
| 26 | + reinterpret_cast<sockaddr_in6*>(addr)->sin6_port); | ||
| 27 | + | ||
| 28 | + if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) { | ||
| 29 | + host = endpoint.host; | ||
| 30 | + DCHECK_EQ(port, std::stoi(endpoint.service)); | ||
| 31 | + } else { | ||
| 32 | + const void* src = family == AF_INET ? | ||
| 33 | + static_cast<void*>( | ||
| 34 | + &(reinterpret_cast<sockaddr_in*>(addr)->sin_addr)) : | ||
| 35 | + static_cast<void*>( | ||
| 36 | + &(reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr)); | ||
| 37 | + if (uv_inet_ntop(family, src, hostbuf, sizeof(hostbuf)) == 0) { | ||
| 38 | + host = hostbuf; | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + writer->json_objectstart(name); | ||
| 42 | + if (host != nullptr) { | ||
| 43 | + writer->json_keyvalue("host", host); | ||
| 44 | + } | ||
| 45 | + writer->json_keyvalue("port", port); | ||
| 46 | + writer->json_objectend(); | ||
| 47 | + } | ||
| 48 | + | ||
| 10 | 49 | // Utility function to format libuv socket information. | |
| 11 | 50 | static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) { | |
| 12 | 51 | struct sockaddr_storage addr_storage; | |
| 13 | 52 | struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); | |
| 14 | 53 | uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h); | |
| 15 | 54 | int addr_size = sizeof(addr_storage); | |
| 16 | 55 | int rc = -1; | |
| 17 | - bool wrote_local_endpoint = false; | ||
| 18 | - bool wrote_remote_endpoint = false; | ||
| 19 | 56 | ||
| 20 | 57 | switch (h->type) { | |
| 21 | 58 | case UV_UDP: | |
@@ -27,38 +64,13 @@ static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) { | |||
| 27 | 64 | default: | |
| 28 | 65 | break; | |
| 29 | 66 | } | |
| 30 | - if (rc == 0) { | ||
| 31 | - // uv_getnameinfo will format host and port and handle IPv4/IPv6. | ||
| 32 | - uv_getnameinfo_t local; | ||
| 33 | - rc = uv_getnameinfo(h->loop, &local, nullptr, addr, NI_NUMERICSERV); | ||
| 34 | - | ||
| 35 | - if (rc == 0) { | ||
| 36 | - writer->json_objectstart("localEndpoint"); | ||
| 37 | - writer->json_keyvalue("host", local.host); | ||
| 38 | - writer->json_keyvalue("port", local.service); | ||
| 39 | - writer->json_objectend(); | ||
| 40 | - wrote_local_endpoint = true; | ||
| 41 | - } | ||
| 42 | - } | ||
| 43 | - if (!wrote_local_endpoint) writer->json_keyvalue("localEndpoint", null); | ||
| 67 | + ReportEndpoint(h, rc == 0 ? addr : nullptr, "localEndpoint", writer); | ||
| 44 | 68 | ||
| 45 | 69 | if (h->type == UV_TCP) { | |
| 46 | 70 | // Get the remote end of the connection. | |
| 47 | 71 | rc = uv_tcp_getpeername(&handle->tcp, addr, &addr_size); | |
| 48 | - if (rc == 0) { | ||
| 49 | - uv_getnameinfo_t remote; | ||
| 50 | - rc = uv_getnameinfo(h->loop, &remote, nullptr, addr, NI_NUMERICSERV); | ||
| 51 | - | ||
| 52 | - if (rc == 0) { | ||
| 53 | - writer->json_objectstart("remoteEndpoint"); | ||
| 54 | - writer->json_keyvalue("host", remote.host); | ||
| 55 | - writer->json_keyvalue("port", remote.service); | ||
| 56 | - writer->json_objectend(); | ||
| 57 | - wrote_local_endpoint = true; | ||
| 58 | - } | ||
| 59 | - } | ||
| 72 | + ReportEndpoint(h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer); | ||
| 60 | 73 | } | |
| 61 | - if (!wrote_remote_endpoint) writer->json_keyvalue("remoteEndpoint", null); | ||
| 62 | 74 | } | |
| 63 | 75 | ||
| 64 | 76 | // Utility function to format libuv path information. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -60,9 +60,7 @@ if (process.argv[2] === 'child') { | |||
| 60 | 60 | const data = { pid: child_process.pid, | |
| 61 | 61 | tcp_address: server.address(), | |
| 62 | 62 | udp_address: udp_socket.address(), | |
| 63 | - skip_fs_watch: (watcher === undefined ? | ||
| 64 | - 'fs.watch() unavailable' : | ||
| 65 | - false) }; | ||
| 63 | + skip_fs_watch: (watcher === undefined) }; | ||
| 66 | 64 | process.send(data); | |
| 67 | 65 | http.get({ port: server.address().port }); | |
| 68 | 66 | }); | |
@@ -74,6 +72,8 @@ if (process.argv[2] === 'child') { | |||
| 74 | 72 | tmpdir.refresh(); | |
| 75 | 73 | const options = { encoding: 'utf8', silent: true, cwd: tmpdir.path }; | |
| 76 | 74 | const child = fork('--experimental-report', [__filename, 'child'], options); | |
| 75 | + let child_data; | ||
| 76 | + child.on('message', (data) => { child_data = data; }); | ||
| 77 | 77 | let stderr = ''; | |
| 78 | 78 | child.stderr.on('data', (chunk) => { stderr += chunk; }); | |
| 79 | 79 | let stdout = ''; | |
@@ -94,36 +94,61 @@ if (process.argv[2] === 'child') { | |||
| 94 | 94 | assert.deepStrictEqual(reports, [], report_msg, reports); | |
| 95 | 95 | ||
| 96 | 96 | const report = JSON.parse(stdout); | |
| 97 | - let fs = 0; | ||
| 98 | - let poll = 0; | ||
| 99 | - let process = 0; | ||
| 100 | - let timer = 0; | ||
| 101 | - let pipe = 0; | ||
| 102 | - let tcp = 0; | ||
| 103 | - let udp = 0; | ||
| 104 | - const fs_msg = 'fs_event not found'; | ||
| 105 | - const poll_msg = 'poll_event not found'; | ||
| 106 | - const process_msg = 'process event not found'; | ||
| 107 | - const timer_msg = 'timer event not found'; | ||
| 108 | - const pipe_msg = 'pipe event not found'; | ||
| 109 | - const tcp_msg = 'tcp event not found'; | ||
| 110 | - const udp_msg = 'udp event not found'; | ||
| 111 | - for (const entry in report.libuv) { | ||
| 112 | - if (report.libuv[entry].type === 'fs_event') fs = 1; | ||
| 113 | - else if (report.libuv[entry].type === 'fs_poll') poll = 1; | ||
| 114 | - else if (report.libuv[entry].type === 'process') process = 1; | ||
| 115 | - else if (report.libuv[entry].type === 'timer') timer = 1; | ||
| 116 | - else if (report.libuv[entry].type === 'pipe') pipe = 1; | ||
| 117 | - else if (report.libuv[entry].type === 'tcp') tcp = 1; | ||
| 118 | - else if (report.libuv[entry].type === 'udp') udp = 1; | ||
| 97 | + const prefix = common.isWindows ? '\\\\?\\' : ''; | ||
| 98 | + const expected_filename = `${prefix}${__filename}`; | ||
| 99 | + const found_tcp = []; | ||
| 100 | + // Functions are named to aid debugging when they are not called. | ||
| 101 | + const validators = { | ||
| 102 | + fs_event: common.mustCall(function fs_event_validator(handle) { | ||
| 103 | + if (!child_data.skip_fs_watch) { | ||
| 104 | + assert.strictEqual(handle.filename, expected_filename); | ||
| 105 | + assert(handle.is_referenced); | ||
| 106 | + } | ||
| 107 | + }), | ||
| 108 | + fs_poll: common.mustCall(function fs_poll_validator(handle) { | ||
| 109 | + assert.strictEqual(handle.filename, expected_filename); | ||
| 110 | + assert(handle.is_referenced); | ||
| 111 | + }), | ||
| 112 | + pipe: common.mustCallAtLeast(function pipe_validator(handle) { | ||
| 113 | + assert(handle.is_referenced); | ||
| 114 | + }), | ||
| 115 | + process: common.mustCall(function process_validator(handle) { | ||
| 116 | + assert.strictEqual(handle.pid, child_data.pid); | ||
| 117 | + assert(handle.is_referenced); | ||
| 118 | + }), | ||
| 119 | + tcp: common.mustCall(function tcp_validator(handle) { | ||
| 120 | + // TCP handles. The report should contain three sockets: | ||
| 121 | + // 1. The server's listening socket. | ||
| 122 | + // 2. The inbound socket making the request. | ||
| 123 | + // 3. The outbound socket sending the response. | ||
| 124 | + const port = child_data.tcp_address.port; | ||
| 125 | + if (handle.localEndpoint.port === port) { | ||
| 126 | + if (handle.remoteEndpoint === null) { | ||
| 127 | + found_tcp.push('listening'); | ||
| 128 | + } else { | ||
| 129 | + found_tcp.push('inbound'); | ||
| 130 | + } | ||
| 131 | + } else if (handle.remoteEndpoint.port === port) { | ||
| 132 | + found_tcp.push('outbound'); | ||
| 133 | + } | ||
| 134 | + assert(handle.is_referenced); | ||
| 135 | + }, 3), | ||
| 136 | + timer: common.mustCall(function timer_validator(handle) { | ||
| 137 | + assert(!handle.is_referenced); | ||
| 138 | + assert.strictEqual(handle.repeat, 0); | ||
| 139 | + }), | ||
| 140 | + udp: common.mustCall(function udp_validator(handle) { | ||
| 141 | + assert.strictEqual(handle.localEndpoint.port, | ||
| 142 | + child_data.udp_address.port); | ||
| 143 | + assert(handle.is_referenced); | ||
| 144 | + }), | ||
| 145 | + }; | ||
| 146 | + for (const entry of report.libuv) { | ||
| 147 | + if (validators[entry.type]) validators[entry.type](entry); | ||
| 148 | + } | ||
| 149 | + for (const socket of ['listening', 'inbound', 'outbound']) { | ||
| 150 | + assert(found_tcp.includes(socket), `${socket} TCP socket was not found`); | ||
| 119 | 151 | } | |
| 120 | - assert.deepStrictEqual(fs, 1, fs_msg); | ||
| 121 | - assert.deepStrictEqual(poll, 1, poll_msg); | ||
| 122 | - assert.deepStrictEqual(process, 1, process_msg); | ||
| 123 | - assert.deepStrictEqual(timer, 1, timer_msg); | ||
| 124 | - assert.deepStrictEqual(pipe, 1, pipe_msg); | ||
| 125 | - assert.deepStrictEqual(tcp, 1, tcp_msg); | ||
| 126 | - assert.deepStrictEqual(udp, 1, udp_msg); | ||
| 127 | 152 | ||
| 128 | 153 | // Common report tests. | |
| 129 | 154 | helper.validateContent(stdout); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments