GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/stream_wrap.cc Lines: 176 181 97.2 %
Date: 2021-04-21 04:11:54 Branches: 57 88 64.8 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "stream_wrap.h"
23
#include "stream_base-inl.h"
24
25
#include "env-inl.h"
26
#include "handle_wrap.h"
27
#include "node_buffer.h"
28
#include "node_external_reference.h"
29
#include "pipe_wrap.h"
30
#include "req_wrap-inl.h"
31
#include "tcp_wrap.h"
32
#include "udp_wrap.h"
33
#include "util-inl.h"
34
35
#include <cstring>  // memcpy()
36
#include <climits>  // INT_MAX
37
38
39
namespace node {
40
41
using v8::Context;
42
using v8::DontDelete;
43
using v8::EscapableHandleScope;
44
using v8::FunctionCallbackInfo;
45
using v8::FunctionTemplate;
46
using v8::HandleScope;
47
using v8::Local;
48
using v8::MaybeLocal;
49
using v8::Object;
50
using v8::PropertyAttribute;
51
using v8::ReadOnly;
52
using v8::Signature;
53
using v8::Value;
54
55
365574
void IsConstructCallCallback(const FunctionCallbackInfo<Value>& args) {
56
365574
  CHECK(args.IsConstructCall());
57
365574
  StreamReq::ResetObject(args.This());
58
365574
}
59
60
462
void LibuvStreamWrap::Initialize(Local<Object> target,
61
                                 Local<Value> unused,
62
                                 Local<Context> context,
63
                                 void* priv) {
64
462
  Environment* env = Environment::GetCurrent(context);
65
66
  Local<FunctionTemplate> sw =
67
462
      FunctionTemplate::New(env->isolate(), IsConstructCallCallback);
68
924
  sw->InstanceTemplate()->SetInternalFieldCount(StreamReq::kInternalFieldCount);
69
70
  // we need to set handle and callback to null,
71
  // so that those fields are created and functions
72
  // do not become megamorphic
73
  // Fields:
74
  // - oncomplete
75
  // - callback
76
  // - handle
77
2310
  sw->InstanceTemplate()->Set(
78
      env->oncomplete_string(),
79
462
      v8::Null(env->isolate()));
80
2310
  sw->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "callback"),
81
462
      v8::Null(env->isolate()));
82
2310
  sw->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "handle"),
83
462
      v8::Null(env->isolate()));
84
85
924
  sw->Inherit(AsyncWrap::GetConstructorTemplate(env));
86
87
462
  env->SetConstructorFunction(target, "ShutdownWrap", sw);
88
462
  env->set_shutdown_wrap_template(sw->InstanceTemplate());
89
90
  Local<FunctionTemplate> ww =
91
462
      FunctionTemplate::New(env->isolate(), IsConstructCallCallback);
92
1386
  ww->InstanceTemplate()->SetInternalFieldCount(
93
462
      StreamReq::kInternalFieldCount);
94
924
  ww->Inherit(AsyncWrap::GetConstructorTemplate(env));
95
462
  env->SetConstructorFunction(target, "WriteWrap", ww);
96
462
  env->set_write_wrap_template(ww->InstanceTemplate());
97
98
462
  NODE_DEFINE_CONSTANT(target, kReadBytesOrError);
99
1386
  NODE_DEFINE_CONSTANT(target, kArrayBufferOffset);
100
2310
  NODE_DEFINE_CONSTANT(target, kBytesWritten);
101
3696
  NODE_DEFINE_CONSTANT(target, kLastWriteWasAsync);
102
4620
  target->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "streamBaseState"),
103
5082
              env->stream_base_state().GetJSArray()).Check();
104
2772
}
105
924
106
4703
void LibuvStreamWrap::RegisterExternalReferences(
107
    ExternalReferenceRegistry* registry) {
108
4703
  registry->Register(IsConstructCallCallback);
109
4703
}
110
111
17645
LibuvStreamWrap::LibuvStreamWrap(Environment* env,
112
                                 Local<Object> object,
113
                                 uv_stream_t* stream,
114
17645
                                 AsyncWrap::ProviderType provider)
115
    : HandleWrap(env,
116
                 object,
117
                 reinterpret_cast<uv_handle_t*>(stream),
118
                 provider),
119
      StreamBase(env),
120
17645
      stream_(stream) {
121
17645
  StreamBase::AttachToObject(object);
122
17645
}
123
124
125
13301
Local<FunctionTemplate> LibuvStreamWrap::GetConstructorTemplate(
126
    Environment* env) {
127
13301
  Local<FunctionTemplate> tmpl = env->libuv_stream_wrap_ctor_template();
128
13301
  if (tmpl.IsEmpty()) {
129
4547
    tmpl = env->NewFunctionTemplate(nullptr);
130
9094
    tmpl->SetClassName(
131
4547
        FIXED_ONE_BYTE_STRING(env->isolate(), "LibuvStreamWrap"));
132
9094
    tmpl->Inherit(HandleWrap::GetConstructorTemplate(env));
133
13641
    tmpl->InstanceTemplate()->SetInternalFieldCount(
134
4547
        StreamBase::kInternalFieldCount);
135
    Local<FunctionTemplate> get_write_queue_size =
136
        FunctionTemplate::New(env->isolate(),
137
                              GetWriteQueueSize,
138
                              Local<Value>(),
139
9094
                              Signature::New(env->isolate(), tmpl));
140
18188
    tmpl->PrototypeTemplate()->SetAccessorProperty(
141
        env->write_queue_size_string(),
142
        get_write_queue_size,
143
        Local<FunctionTemplate>(),
144
4547
        static_cast<PropertyAttribute>(ReadOnly | DontDelete));
145
4547
    env->SetProtoMethod(tmpl, "setBlocking", SetBlocking);
146
4547
    StreamBase::AddMethods(env, tmpl);
147
4547
    env->set_libuv_stream_wrap_ctor_template(tmpl);
148
  }
149
13301
  return tmpl;
150
}
151
152
153
3537
LibuvStreamWrap* LibuvStreamWrap::From(Environment* env, Local<Object> object) {
154
3537
  Local<FunctionTemplate> sw = env->libuv_stream_wrap_ctor_template();
155

7074
  CHECK(!sw.IsEmpty() && sw->HasInstance(object));
156
3537
  return Unwrap<LibuvStreamWrap>(object);
157
}
158
159
160
119
int LibuvStreamWrap::GetFD() {
161
#ifdef _WIN32
162
  return fd_;
163
#else
164
119
  int fd = -1;
165
119
  if (stream() != nullptr)
166
119
    uv_fileno(reinterpret_cast<uv_handle_t*>(stream()), &fd);
167
119
  return fd;
168
#endif
169
}
170
171
172
372238
bool LibuvStreamWrap::IsAlive() {
173
372238
  return HandleWrap::IsAlive(this);
174
}
175
176
177
3
bool LibuvStreamWrap::IsClosing() {
178
3
  return uv_is_closing(reinterpret_cast<uv_handle_t*>(stream()));
179
}
180
181
182
660752
AsyncWrap* LibuvStreamWrap::GetAsyncWrap() {
183
660752
  return static_cast<AsyncWrap*>(this);
184
}
185
186
187
274740
bool LibuvStreamWrap::IsIPCPipe() {
188
274740
  return is_named_pipe_ipc();
189
}
190
191
192
21639
int LibuvStreamWrap::ReadStart() {
193
43278
  return uv_read_start(stream(), [](uv_handle_t* handle,
194
                                    size_t suggested_size,
195
658653
                                    uv_buf_t* buf) {
196
318507
    static_cast<LibuvStreamWrap*>(handle->data)->OnUvAlloc(suggested_size, buf);
197
1317772
  }, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
198
318740
    static_cast<LibuvStreamWrap*>(stream->data)->OnUvRead(nread, buf);
199
702313
  });
200
}
201
202
203
15832
int LibuvStreamWrap::ReadStop() {
204
15832
  return uv_read_stop(stream());
205
}
206
207
208
318507
void LibuvStreamWrap::OnUvAlloc(size_t suggested_size, uv_buf_t* buf) {
209
637014
  HandleScope scope(env()->isolate());
210
318507
  Context::Scope context_scope(env()->context());
211
212
318507
  *buf = EmitAlloc(suggested_size);
213
318507
}
214
215
template <class WrapType>
216
158
static MaybeLocal<Object> AcceptHandle(Environment* env,
217
                                       LibuvStreamWrap* parent) {
218
  static_assert(std::is_base_of<LibuvStreamWrap, WrapType>::value ||
219
                std::is_base_of<UDPWrap, WrapType>::value,
220
                "Can only accept stream handles");
221
222
158
  EscapableHandleScope scope(env->isolate());
223
  Local<Object> wrap_obj;
224
225

316
  if (!WrapType::Instantiate(env, parent, WrapType::SOCKET).ToLocal(&wrap_obj))
226
    return Local<Object>();
227
228
158
  HandleWrap* wrap = Unwrap<HandleWrap>(wrap_obj);
229

158
  CHECK_NOT_NULL(wrap);
230
158
  uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(wrap->GetHandle());
231

158
  CHECK_NOT_NULL(stream);
232
233

158
  if (uv_accept(parent->stream(), stream))
234
    ABORT();
235
236
158
  return scope.Escape(wrap_obj);
237
}
238
239
240
318740
void LibuvStreamWrap::OnUvRead(ssize_t nread, const uv_buf_t* buf) {
241
637396
  HandleScope scope(env()->isolate());
242
318740
  Context::Scope context_scope(env()->context());
243
318740
  uv_handle_type type = UV_UNKNOWN_HANDLE;
244
245

322544
  if (is_named_pipe_ipc() &&
246
3804
      uv_pipe_pending_count(reinterpret_cast<uv_pipe_t*>(stream())) > 0) {
247
158
    type = uv_pipe_pending_type(reinterpret_cast<uv_pipe_t*>(stream()));
248
  }
249
250
  // We should not be getting this callback if someone has already called
251
  // uv_close() on the handle.
252
637480
  CHECK_EQ(persistent().IsEmpty(), false);
253
254
318740
  if (nread > 0) {
255
    MaybeLocal<Object> pending_obj;
256
257
312710
    if (type == UV_TCP) {
258
127
      pending_obj = AcceptHandle<TCPWrap>(env(), this);
259
312583
    } else if (type == UV_NAMED_PIPE) {
260
1
      pending_obj = AcceptHandle<PipeWrap>(env(), this);
261
312582
    } else if (type == UV_UDP) {
262
30
      pending_obj = AcceptHandle<UDPWrap>(env(), this);
263
    } else {
264
312552
      CHECK_EQ(type, UV_UNKNOWN_HANDLE);
265
    }
266
267
312710
    if (!pending_obj.IsEmpty()) {
268
316
      object()
269
316
          ->Set(env()->context(),
270
                env()->pending_handle_string(),
271
632
                pending_obj.ToLocalChecked())
272
          .Check();
273
    }
274
  }
275
276
318740
  EmitRead(nread, *buf);
277
318656
}
278
279
280
5405
void LibuvStreamWrap::GetWriteQueueSize(
281
    const FunctionCallbackInfo<Value>& info) {
282
  LibuvStreamWrap* wrap;
283
5405
  ASSIGN_OR_RETURN_UNWRAP(&wrap, info.This());
284
285
5405
  if (wrap->stream() == nullptr) {
286
    info.GetReturnValue().Set(0);
287
    return;
288
  }
289
290
5405
  uint32_t write_queue_size = wrap->stream()->write_queue_size;
291
10810
  info.GetReturnValue().Set(write_queue_size);
292
}
293
294
295
31
void LibuvStreamWrap::SetBlocking(const FunctionCallbackInfo<Value>& args) {
296
  LibuvStreamWrap* wrap;
297
31
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
298
299
31
  CHECK_GT(args.Length(), 0);
300
31
  if (!wrap->IsAlive())
301
    return args.GetReturnValue().Set(UV_EINVAL);
302
303
62
  bool enable = args[0]->IsTrue();
304
93
  args.GetReturnValue().Set(uv_stream_set_blocking(wrap->stream(), enable));
305
}
306
307
typedef SimpleShutdownWrap<ReqWrap<uv_shutdown_t>> LibuvShutdownWrap;
308
typedef SimpleWriteWrap<ReqWrap<uv_write_t>> LibuvWriteWrap;
309
310
7285
ShutdownWrap* LibuvStreamWrap::CreateShutdownWrap(Local<Object> object) {
311
7285
  return new LibuvShutdownWrap(this, object);
312
}
313
314
247
WriteWrap* LibuvStreamWrap::CreateWriteWrap(Local<Object> object) {
315
247
  return new LibuvWriteWrap(this, object);
316
}
317
318
319
7285
int LibuvStreamWrap::DoShutdown(ShutdownWrap* req_wrap_) {
320
7285
  LibuvShutdownWrap* req_wrap = static_cast<LibuvShutdownWrap*>(req_wrap_);
321
7285
  return req_wrap->Dispatch(uv_shutdown, stream(), AfterUvShutdown);
322
}
323
324
325
7282
void LibuvStreamWrap::AfterUvShutdown(uv_shutdown_t* req, int status) {
326
7282
  LibuvShutdownWrap* req_wrap = static_cast<LibuvShutdownWrap*>(
327
14564
      LibuvShutdownWrap::from_req(req));
328
7282
  CHECK_NOT_NULL(req_wrap);
329
14564
  HandleScope scope(req_wrap->env()->isolate());
330
7282
  Context::Scope context_scope(req_wrap->env()->context());
331
7282
  req_wrap->Done(status);
332
7282
}
333
334
335
// NOTE: Call to this function could change both `buf`'s and `count`'s
336
// values, shifting their base and decrementing their length. This is
337
// required in order to skip the data that was successfully written via
338
// uv_try_write().
339
366356
int LibuvStreamWrap::DoTryWrite(uv_buf_t** bufs, size_t* count) {
340
  int err;
341
  size_t written;
342
366356
  uv_buf_t* vbufs = *bufs;
343
366356
  size_t vcount = *count;
344
345
366356
  err = uv_try_write(stream(), vbufs, vcount);
346

366356
  if (err == UV_ENOSYS || err == UV_EAGAIN)
347
10
    return 0;
348
366346
  if (err < 0)
349
1999
    return err;
350
351
  // Slice off the buffers: skip all written buffers and slice the one that
352
  // was partially written.
353
364347
  written = err;
354
1240339
  for (; vcount > 0; vbufs++, vcount--) {
355
    // Slice
356
438129
    if (vbufs[0].len > written) {
357
133
      vbufs[0].base += written;
358
133
      vbufs[0].len -= written;
359
133
      written = 0;
360
133
      break;
361
362
    // Discard
363
    } else {
364
437996
      written -= vbufs[0].len;
365
    }
366
  }
367
368
364347
  *bufs = vbufs;
369
364347
  *count = vcount;
370
371
364347
  return 0;
372
}
373
374
375
247
int LibuvStreamWrap::DoWrite(WriteWrap* req_wrap,
376
                             uv_buf_t* bufs,
377
                             size_t count,
378
                             uv_stream_t* send_handle) {
379
247
  LibuvWriteWrap* w = static_cast<LibuvWriteWrap*>(req_wrap);
380
247
  return w->Dispatch(uv_write2,
381
                     stream(),
382
                     bufs,
383
                     count,
384
                     send_handle,
385
247
                     AfterUvWrite);
386
}
387
388
389
390
246
void LibuvStreamWrap::AfterUvWrite(uv_write_t* req, int status) {
391
246
  LibuvWriteWrap* req_wrap = static_cast<LibuvWriteWrap*>(
392
492
      LibuvWriteWrap::from_req(req));
393
246
  CHECK_NOT_NULL(req_wrap);
394
491
  HandleScope scope(req_wrap->env()->isolate());
395
246
  Context::Scope context_scope(req_wrap->env()->context());
396
246
  req_wrap->Done(status);
397
245
}
398
399
}  // namespace node
400
401
4762
NODE_MODULE_CONTEXT_AWARE_INTERNAL(stream_wrap,
402
                                   node::LibuvStreamWrap::Initialize)
403

19013
NODE_MODULE_EXTERNAL_REFERENCE(
404
    stream_wrap, node::LibuvStreamWrap::RegisterExternalReferences)