GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/udp_wrap.cc Lines: 221 233 94.8 %
Date: 2019-02-13 22:28:58 Branches: 80 144 55.6 %

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 "udp_wrap.h"
23
#include "env-inl.h"
24
#include "node_buffer.h"
25
#include "handle_wrap.h"
26
#include "req_wrap-inl.h"
27
#include "util-inl.h"
28
29
namespace node {
30
31
using v8::Array;
32
using v8::Context;
33
using v8::FunctionCallbackInfo;
34
using v8::FunctionTemplate;
35
using v8::HandleScope;
36
using v8::Integer;
37
using v8::Local;
38
using v8::MaybeLocal;
39
using v8::Object;
40
using v8::PropertyAttribute;
41
using v8::Signature;
42
using v8::String;
43
using v8::Uint32;
44
using v8::Undefined;
45
using v8::Value;
46
47
using AsyncHooks = Environment::AsyncHooks;
48
49
50
16824
class SendWrap : public ReqWrap<uv_udp_send_t> {
51
 public:
52
  SendWrap(Environment* env, Local<Object> req_wrap_obj, bool have_callback);
53
  inline bool have_callback() const;
54
  size_t msg_size;
55
56
  SET_NO_MEMORY_INFO()
57
  SET_MEMORY_INFO_NAME(SendWrap)
58
  SET_SELF_SIZE(SendWrap)
59
60
 private:
61
  const bool have_callback_;
62
};
63
64
65
8416
SendWrap::SendWrap(Environment* env,
66
                   Local<Object> req_wrap_obj,
67
                   bool have_callback)
68
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_UDPSENDWRAP),
69
8416
      have_callback_(have_callback) {
70
8416
}
71
72
73
8412
inline bool SendWrap::have_callback() const {
74
8412
  return have_callback_;
75
}
76
77
78
228
UDPWrap::UDPWrap(Environment* env, Local<Object> object)
79
    : HandleWrap(env,
80
                 object,
81
                 reinterpret_cast<uv_handle_t*>(&handle_),
82
228
                 AsyncWrap::PROVIDER_UDPWRAP) {
83
228
  int r = uv_udp_init(env->event_loop(), &handle_);
84
228
  CHECK_EQ(r, 0);  // can't fail anyway
85
228
}
86
87
88
3794
void UDPWrap::Initialize(Local<Object> target,
89
                         Local<Value> unused,
90
                         Local<Context> context,
91
                         void* priv) {
92
3794
  Environment* env = Environment::GetCurrent(context);
93
94
3794
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
95
7588
  t->InstanceTemplate()->SetInternalFieldCount(1);
96
  Local<String> udpString =
97
3794
      FIXED_ONE_BYTE_STRING(env->isolate(), "UDP");
98
3794
  t->SetClassName(udpString);
99
100
  enum PropertyAttribute attributes =
101
3794
      static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
102
103
3794
  Local<Signature> signature = Signature::New(env->isolate(), t);
104
105
  Local<FunctionTemplate> get_fd_templ =
106
      FunctionTemplate::New(env->isolate(),
107
                            UDPWrap::GetFD,
108
                            env->as_external(),
109
7588
                            signature);
110
111
11382
  t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
112
                                              get_fd_templ,
113
                                              Local<FunctionTemplate>(),
114
11382
                                              attributes);
115
116
3794
  env->SetProtoMethod(t, "open", Open);
117
3794
  env->SetProtoMethod(t, "bind", Bind);
118
3794
  env->SetProtoMethod(t, "send", Send);
119
3794
  env->SetProtoMethod(t, "bind6", Bind6);
120
3794
  env->SetProtoMethod(t, "send6", Send6);
121
3794
  env->SetProtoMethod(t, "recvStart", RecvStart);
122
3794
  env->SetProtoMethod(t, "recvStop", RecvStop);
123
  env->SetProtoMethod(t, "getsockname",
124
3794
                      GetSockOrPeerName<UDPWrap, uv_udp_getsockname>);
125
3794
  env->SetProtoMethod(t, "addMembership", AddMembership);
126
3794
  env->SetProtoMethod(t, "dropMembership", DropMembership);
127
3794
  env->SetProtoMethod(t, "setMulticastInterface", SetMulticastInterface);
128
3794
  env->SetProtoMethod(t, "setMulticastTTL", SetMulticastTTL);
129
3794
  env->SetProtoMethod(t, "setMulticastLoopback", SetMulticastLoopback);
130
3794
  env->SetProtoMethod(t, "setBroadcast", SetBroadcast);
131
3794
  env->SetProtoMethod(t, "setTTL", SetTTL);
132
3794
  env->SetProtoMethod(t, "bufferSize", BufferSize);
133
134
7588
  t->Inherit(HandleWrap::GetConstructorTemplate(env));
135
136
  target->Set(env->context(),
137
              udpString,
138
18970
              t->GetFunction(env->context()).ToLocalChecked()).FromJust();
139
  env->set_udp_constructor_function(
140
11382
      t->GetFunction(env->context()).ToLocalChecked());
141
142
  // Create FunctionTemplate for SendWrap
143
  Local<FunctionTemplate> swt =
144
3794
      BaseObject::MakeLazilyInitializedJSTemplate(env);
145
7588
  swt->Inherit(AsyncWrap::GetConstructorTemplate(env));
146
  Local<String> sendWrapString =
147
3794
      FIXED_ONE_BYTE_STRING(env->isolate(), "SendWrap");
148
3794
  swt->SetClassName(sendWrapString);
149
  target->Set(env->context(),
150
              sendWrapString,
151
18970
              swt->GetFunction(env->context()).ToLocalChecked()).FromJust();
152
153
3794
  Local<Object> constants = Object::New(env->isolate());
154
15176
  NODE_DEFINE_CONSTANT(constants, UV_UDP_IPV6ONLY);
155
  target->Set(context,
156
              env->constants_string(),
157
11382
              constants).FromJust();
158
3794
}
159
160
161
228
void UDPWrap::New(const FunctionCallbackInfo<Value>& args) {
162
228
  CHECK(args.IsConstructCall());
163
228
  Environment* env = Environment::GetCurrent(args);
164
228
  new UDPWrap(env, args.This());
165
228
}
166
167
168
21
void UDPWrap::GetFD(const FunctionCallbackInfo<Value>& args) {
169
21
  int fd = UV_EBADF;
170
#if !defined(_WIN32)
171
21
  UDPWrap* wrap = Unwrap<UDPWrap>(args.This());
172
21
  if (wrap != nullptr)
173
20
    uv_fileno(reinterpret_cast<uv_handle_t*>(&wrap->handle_), &fd);
174
#endif
175
63
  args.GetReturnValue().Set(fd);
176
21
}
177
178
179
119
void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
180
  UDPWrap* wrap;
181
119
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
182
                          args.Holder(),
183
                          args.GetReturnValue().Set(UV_EBADF));
184
185
  // bind(ip, port, flags)
186
119
  CHECK_EQ(args.Length(), 3);
187
188
119
  node::Utf8Value address(args.GetIsolate(), args[0]);
189
119
  Local<Context> ctx = args.GetIsolate()->GetCurrentContext();
190
  uint32_t port, flags;
191


833
  if (!args[1]->Uint32Value(ctx).To(&port) ||
192

476
      !args[2]->Uint32Value(ctx).To(&flags))
193
    return;
194
  char addr[sizeof(sockaddr_in6)];
195
  int err;
196
197
119
  switch (family) {
198
  case AF_INET:
199
108
    err = uv_ip4_addr(*address, port, reinterpret_cast<sockaddr_in*>(&addr));
200
108
    break;
201
  case AF_INET6:
202
11
    err = uv_ip6_addr(*address, port, reinterpret_cast<sockaddr_in6*>(&addr));
203
11
    break;
204
  default:
205
    CHECK(0 && "unexpected address family");
206
    ABORT();
207
  }
208
209
119
  if (err == 0) {
210
    err = uv_udp_bind(&wrap->handle_,
211
                      reinterpret_cast<const sockaddr*>(&addr),
212
118
                      flags);
213
  }
214
215
238
  args.GetReturnValue().Set(err);
216
}
217
218
219
6
void UDPWrap::Open(const FunctionCallbackInfo<Value>& args) {
220
  UDPWrap* wrap;
221
12
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
222
                          args.Holder(),
223
                          args.GetReturnValue().Set(UV_EBADF));
224
12
  CHECK(args[0]->IsNumber());
225
18
  int fd = static_cast<int>(args[0].As<Integer>()->Value());
226
6
  int err = uv_udp_open(&wrap->handle_, fd);
227
228
12
  args.GetReturnValue().Set(err);
229
}
230
231
232
108
void UDPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
233
108
  DoBind(args, AF_INET);
234
108
}
235
236
237
11
void UDPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
238
11
  DoBind(args, AF_INET6);
239
11
}
240
241
242
30
void UDPWrap::BufferSize(const FunctionCallbackInfo<Value>& args) {
243
30
  Environment* env = Environment::GetCurrent(args);
244
  UDPWrap* wrap;
245
36
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
246
                          args.Holder(),
247
                          args.GetReturnValue().Set(UV_EBADF));
248
249
60
  CHECK(args[0]->IsUint32());
250
60
  CHECK(args[1]->IsBoolean());
251
90
  bool is_recv = args[1].As<v8::Boolean>()->Value();
252
  const char* uv_func_name = is_recv ? "uv_recv_buffer_size" :
253
30
                                       "uv_send_buffer_size";
254
255
60
  if (!args[0]->IsInt32()) {
256
2
    env->CollectUVExceptionInfo(args[2], UV_EINVAL, uv_func_name);
257
4
    return args.GetReturnValue().SetUndefined();
258
  }
259
260
28
  uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&wrap->handle_);
261
84
  int size = static_cast<int>(args[0].As<Uint32>()->Value());
262
  int err;
263
264
28
  if (is_recv)
265
15
    err = uv_recv_buffer_size(handle, &size);
266
  else
267
13
    err = uv_send_buffer_size(handle, &size);
268
269
28
  if (err != 0) {
270
4
    env->CollectUVExceptionInfo(args[2], err, uv_func_name);
271
8
    return args.GetReturnValue().SetUndefined();
272
  }
273
274
72
  args.GetReturnValue().Set(size);
275
}
276
277
#define X(name, fn)                                                            \
278
  void UDPWrap::name(const FunctionCallbackInfo<Value>& args) {                \
279
    UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder());                            \
280
    Environment* env = wrap->env();                                            \
281
    CHECK_EQ(args.Length(), 1);                                                \
282
    int flag;                                                                  \
283
    if (!args[0]->Int32Value(env->context()).To(&flag)) {                      \
284
      return;                                                                  \
285
    }                                                                          \
286
    int err = wrap == nullptr ? UV_EBADF : fn(&wrap->handle_, flag);           \
287
    args.GetReturnValue().Set(err);                                            \
288
  }
289
290

24
X(SetTTL, uv_udp_set_ttl)
291

40
X(SetBroadcast, uv_udp_set_broadcast)
292

24
X(SetMulticastTTL, uv_udp_set_multicast_ttl)
293

32
X(SetMulticastLoopback, uv_udp_set_multicast_loop)
294
295
#undef X
296
297
9
void UDPWrap::SetMulticastInterface(const FunctionCallbackInfo<Value>& args) {
298
  UDPWrap* wrap;
299
18
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
300
                          args.Holder(),
301
                          args.GetReturnValue().Set(UV_EBADF));
302
303
9
  CHECK_EQ(args.Length(), 1);
304
27
  CHECK(args[0]->IsString());
305
306
9
  Utf8Value iface(args.GetIsolate(), args[0]);
307
308
9
  const char* iface_cstr = *iface;
309
310
9
  int err = uv_udp_set_multicast_interface(&wrap->handle_, iface_cstr);
311
18
  args.GetReturnValue().Set(err);
312
}
313
314
6
void UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args,
315
                            uv_membership membership) {
316
  UDPWrap* wrap;
317
12
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
318
                          args.Holder(),
319
                          args.GetReturnValue().Set(UV_EBADF));
320
321
6
  CHECK_EQ(args.Length(), 2);
322
323
6
  node::Utf8Value address(args.GetIsolate(), args[0]);
324
12
  node::Utf8Value iface(args.GetIsolate(), args[1]);
325
326
6
  const char* iface_cstr = *iface;
327


24
  if (args[1]->IsUndefined() || args[1]->IsNull()) {
328
6
      iface_cstr = nullptr;
329
  }
330
331
  int err = uv_udp_set_membership(&wrap->handle_,
332
6
                                  *address,
333
                                  iface_cstr,
334
6
                                  membership);
335
18
  args.GetReturnValue().Set(err);
336
}
337
338
339
3
void UDPWrap::AddMembership(const FunctionCallbackInfo<Value>& args) {
340
3
  SetMembership(args, UV_JOIN_GROUP);
341
3
}
342
343
344
3
void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) {
345
3
  SetMembership(args, UV_LEAVE_GROUP);
346
3
}
347
348
349
8416
void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
350
8416
  Environment* env = Environment::GetCurrent(args);
351
352
  UDPWrap* wrap;
353
16832
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
354
                          args.Holder(),
355
                          args.GetReturnValue().Set(UV_EBADF));
356
357
  // send(req, list, list.length, port, address, hasCallback)
358
16832
  CHECK(args[0]->IsObject());
359
16832
  CHECK(args[1]->IsArray());
360
16832
  CHECK(args[2]->IsUint32());
361
16832
  CHECK(args[3]->IsUint32());
362
25248
  CHECK(args[4]->IsString());
363
16832
  CHECK(args[5]->IsBoolean());
364
365
16832
  Local<Object> req_wrap_obj = args[0].As<Object>();
366
16832
  Local<Array> chunks = args[1].As<Array>();
367
  // it is faster to fetch the length of the
368
  // array in js-land
369
25248
  size_t count = args[2].As<Uint32>()->Value();
370
25248
  const unsigned short port = args[3].As<Uint32>()->Value();
371
8416
  node::Utf8Value address(env->isolate(), args[4]);
372
16832
  const bool have_callback = args[5]->IsTrue();
373
374
  SendWrap* req_wrap;
375
  {
376
8416
    AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
377
8416
    req_wrap = new SendWrap(env, req_wrap_obj, have_callback);
378
  }
379
8416
  size_t msg_size = 0;
380
381
16832
  MaybeStackBuffer<uv_buf_t, 16> bufs(count);
382
383
  // construct uv_buf_t array
384
20901
  for (size_t i = 0; i < count; i++) {
385
37455
    Local<Value> chunk = chunks->Get(env->context(), i).ToLocalChecked();
386
387
12485
    size_t length = Buffer::Length(chunk);
388
389
12485
    bufs[i] = uv_buf_init(Buffer::Data(chunk), length);
390
12485
    msg_size += length;
391
  }
392
393
8416
  req_wrap->msg_size = msg_size;
394
395
  char addr[sizeof(sockaddr_in6)];
396
  int err;
397
398
8416
  switch (family) {
399
  case AF_INET:
400
8410
    err = uv_ip4_addr(*address, port, reinterpret_cast<sockaddr_in*>(&addr));
401
8410
    break;
402
  case AF_INET6:
403
6
    err = uv_ip6_addr(*address, port, reinterpret_cast<sockaddr_in6*>(&addr));
404
6
    break;
405
  default:
406
    CHECK(0 && "unexpected address family");
407
    ABORT();
408
  }
409
410
8416
  if (err == 0) {
411
    err = req_wrap->Dispatch(uv_udp_send,
412
                             &wrap->handle_,
413
                             *bufs,
414
                             count,
415
                             reinterpret_cast<const sockaddr*>(&addr),
416
8416
                             OnSend);
417
  }
418
419
8416
  if (err)
420
    delete req_wrap;
421
422
25248
  args.GetReturnValue().Set(err);
423
}
424
425
426
8410
void UDPWrap::Send(const FunctionCallbackInfo<Value>& args) {
427
8410
  DoSend(args, AF_INET);
428
8410
}
429
430
431
6
void UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) {
432
6
  DoSend(args, AF_INET6);
433
6
}
434
435
436
123
void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) {
437
  UDPWrap* wrap;
438
246
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
439
                          args.Holder(),
440
                          args.GetReturnValue().Set(UV_EBADF));
441
123
  int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
442
  // UV_EALREADY means that the socket is already bound but that's okay
443
123
  if (err == UV_EALREADY)
444
    err = 0;
445
246
  args.GetReturnValue().Set(err);
446
}
447
448
449
108
void UDPWrap::RecvStop(const FunctionCallbackInfo<Value>& args) {
450
  UDPWrap* wrap;
451
216
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
452
                          args.Holder(),
453
                          args.GetReturnValue().Set(UV_EBADF));
454
108
  int r = uv_udp_recv_stop(&wrap->handle_);
455
216
  args.GetReturnValue().Set(r);
456
}
457
458
459
8412
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
460
8412
  SendWrap* req_wrap = static_cast<SendWrap*>(req->data);
461
8412
  if (req_wrap->have_callback()) {
462
8241
    Environment* env = req_wrap->env();
463
8241
    HandleScope handle_scope(env->isolate());
464
8241
    Context::Scope context_scope(env->context());
465
    Local<Value> arg[] = {
466
      Integer::New(env->isolate(), status),
467
      Integer::New(env->isolate(), req_wrap->msg_size),
468
24723
    };
469
16482
    req_wrap->MakeCallback(env->oncomplete_string(), 2, arg);
470
  }
471
8412
  delete req_wrap;
472
8412
}
473
474
475
12611
void UDPWrap::OnAlloc(uv_handle_t* handle,
476
                      size_t suggested_size,
477
                      uv_buf_t* buf) {
478
12611
  buf->base = node::Malloc(suggested_size);
479
12611
  buf->len = suggested_size;
480
12611
}
481
482
483
12611
void UDPWrap::OnRecv(uv_udp_t* handle,
484
                     ssize_t nread,
485
                     const uv_buf_t* buf,
486
                     const struct sockaddr* addr,
487
                     unsigned int flags) {
488

12611
  if (nread == 0 && addr == nullptr) {
489
4225
    if (buf->base != nullptr)
490
4225
      free(buf->base);
491
8450
    return;
492
  }
493
494
8386
  UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
495
8386
  Environment* env = wrap->env();
496
497
8386
  HandleScope handle_scope(env->isolate());
498
16772
  Context::Scope context_scope(env->context());
499
500
8386
  Local<Object> wrap_obj = wrap->object();
501
  Local<Value> argv[] = {
502
    Integer::New(env->isolate(), nread),
503
    wrap_obj,
504
    Undefined(env->isolate()),
505
    Undefined(env->isolate())
506
41930
  };
507
508
8386
  if (nread < 0) {
509
    if (buf->base != nullptr)
510
      free(buf->base);
511
    wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
512
    return;
513
  }
514
515
8386
  char* base = node::UncheckedRealloc(buf->base, nread);
516
16772
  argv[2] = Buffer::New(env, base, nread).ToLocalChecked();
517
16772
  argv[3] = AddressToJS(env, addr);
518
16772
  wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
519
}
520
521
26
MaybeLocal<Object> UDPWrap::Instantiate(Environment* env,
522
                                        AsyncWrap* parent,
523
                                        UDPWrap::SocketType type) {
524
26
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent);
525
526
  // If this assert fires then Initialize hasn't been called yet.
527
52
  CHECK_EQ(env->udp_constructor_function().IsEmpty(), false);
528
52
  return env->udp_constructor_function()->NewInstance(env->context());
529
}
530
531
532
}  // namespace node
533
534
4314
NODE_MODULE_CONTEXT_AWARE_INTERNAL(udp_wrap, node::UDPWrap::Initialize)