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: 217 226 96.0 %
Date: 2019-02-26 22:23:30 Branches: 78 137 56.9 %

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
16176
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
8092
SendWrap::SendWrap(Environment* env,
66
                   Local<Object> req_wrap_obj,
67
                   bool have_callback)
68
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_UDPSENDWRAP),
69
8092
      have_callback_(have_callback) {
70
8092
}
71
72
73
8088
inline bool SendWrap::have_callback() const {
74
8088
  return have_callback_;
75
}
76
77
78
226
UDPWrap::UDPWrap(Environment* env, Local<Object> object)
79
    : HandleWrap(env,
80
                 object,
81
                 reinterpret_cast<uv_handle_t*>(&handle_),
82
226
                 AsyncWrap::PROVIDER_UDPWRAP) {
83
226
  int r = uv_udp_init(env->event_loop(), &handle_);
84
226
  CHECK_EQ(r, 0);  // can't fail anyway
85
226
}
86
87
88
3766
void UDPWrap::Initialize(Local<Object> target,
89
                         Local<Value> unused,
90
                         Local<Context> context,
91
                         void* priv) {
92
3766
  Environment* env = Environment::GetCurrent(context);
93
94
3766
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
95
7532
  t->InstanceTemplate()->SetInternalFieldCount(1);
96
  Local<String> udpString =
97
3766
      FIXED_ONE_BYTE_STRING(env->isolate(), "UDP");
98
3766
  t->SetClassName(udpString);
99
100
  enum PropertyAttribute attributes =
101
3766
      static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
102
103
3766
  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
7532
                            signature);
110
111
11298
  t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
112
                                              get_fd_templ,
113
                                              Local<FunctionTemplate>(),
114
11298
                                              attributes);
115
116
3766
  env->SetProtoMethod(t, "open", Open);
117
3766
  env->SetProtoMethod(t, "bind", Bind);
118
3766
  env->SetProtoMethod(t, "send", Send);
119
3766
  env->SetProtoMethod(t, "bind6", Bind6);
120
3766
  env->SetProtoMethod(t, "send6", Send6);
121
3766
  env->SetProtoMethod(t, "recvStart", RecvStart);
122
3766
  env->SetProtoMethod(t, "recvStop", RecvStop);
123
  env->SetProtoMethod(t, "getsockname",
124
3766
                      GetSockOrPeerName<UDPWrap, uv_udp_getsockname>);
125
3766
  env->SetProtoMethod(t, "addMembership", AddMembership);
126
3766
  env->SetProtoMethod(t, "dropMembership", DropMembership);
127
3766
  env->SetProtoMethod(t, "setMulticastInterface", SetMulticastInterface);
128
3766
  env->SetProtoMethod(t, "setMulticastTTL", SetMulticastTTL);
129
3766
  env->SetProtoMethod(t, "setMulticastLoopback", SetMulticastLoopback);
130
3766
  env->SetProtoMethod(t, "setBroadcast", SetBroadcast);
131
3766
  env->SetProtoMethod(t, "setTTL", SetTTL);
132
3766
  env->SetProtoMethod(t, "bufferSize", BufferSize);
133
134
7532
  t->Inherit(HandleWrap::GetConstructorTemplate(env));
135
136
  target->Set(env->context(),
137
              udpString,
138
18830
              t->GetFunction(env->context()).ToLocalChecked()).FromJust();
139
  env->set_udp_constructor_function(
140
11298
      t->GetFunction(env->context()).ToLocalChecked());
141
142
  // Create FunctionTemplate for SendWrap
143
  Local<FunctionTemplate> swt =
144
3766
      BaseObject::MakeLazilyInitializedJSTemplate(env);
145
7532
  swt->Inherit(AsyncWrap::GetConstructorTemplate(env));
146
  Local<String> sendWrapString =
147
3766
      FIXED_ONE_BYTE_STRING(env->isolate(), "SendWrap");
148
3766
  swt->SetClassName(sendWrapString);
149
  target->Set(env->context(),
150
              sendWrapString,
151
18830
              swt->GetFunction(env->context()).ToLocalChecked()).FromJust();
152
153
3766
  Local<Object> constants = Object::New(env->isolate());
154
15064
  NODE_DEFINE_CONSTANT(constants, UV_UDP_IPV6ONLY);
155
  target->Set(context,
156
              env->constants_string(),
157
11298
              constants).FromJust();
158
3766
}
159
160
161
226
void UDPWrap::New(const FunctionCallbackInfo<Value>& args) {
162
226
  CHECK(args.IsConstructCall());
163
226
  Environment* env = Environment::GetCurrent(args);
164
226
  new UDPWrap(env, args.This());
165
226
}
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
8211
int sockaddr_for_family(int address_family,
179
                        const char* address,
180
                        const unsigned short port,
181
                        struct sockaddr_storage* addr) {
182
8211
  switch (address_family) {
183
  case AF_INET:
184
8194
    return uv_ip4_addr(address, port, reinterpret_cast<sockaddr_in*>(addr));
185
  case AF_INET6:
186
17
    return uv_ip6_addr(address, port, reinterpret_cast<sockaddr_in6*>(addr));
187
  default:
188
    CHECK(0 && "unexpected address family");
189
  }
190
}
191
192
119
void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
193
  UDPWrap* wrap;
194
119
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
195
                          args.Holder(),
196
                          args.GetReturnValue().Set(UV_EBADF));
197
198
  // bind(ip, port, flags)
199
119
  CHECK_EQ(args.Length(), 3);
200
201
119
  node::Utf8Value address(args.GetIsolate(), args[0]);
202
119
  Local<Context> ctx = args.GetIsolate()->GetCurrentContext();
203
  uint32_t port, flags;
204


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

476
      !args[2]->Uint32Value(ctx).To(&flags))
206
    return;
207
  struct sockaddr_storage addr_storage;
208
119
  int err = sockaddr_for_family(family, address.out(), port, &addr_storage);
209
119
  if (err == 0) {
210
    err = uv_udp_bind(&wrap->handle_,
211
                      reinterpret_cast<const sockaddr*>(&addr_storage),
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
8092
void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
350
8092
  Environment* env = Environment::GetCurrent(args);
351
352
  UDPWrap* wrap;
353
16184
  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
16184
  CHECK(args[0]->IsObject());
359
16184
  CHECK(args[1]->IsArray());
360
16184
  CHECK(args[2]->IsUint32());
361
16184
  CHECK(args[3]->IsUint32());
362
24276
  CHECK(args[4]->IsString());
363
16184
  CHECK(args[5]->IsBoolean());
364
365
16184
  Local<Object> req_wrap_obj = args[0].As<Object>();
366
16184
  Local<Array> chunks = args[1].As<Array>();
367
  // it is faster to fetch the length of the
368
  // array in js-land
369
24276
  size_t count = args[2].As<Uint32>()->Value();
370
24276
  const unsigned short port = args[3].As<Uint32>()->Value();
371
8092
  node::Utf8Value address(env->isolate(), args[4]);
372
16184
  const bool have_callback = args[5]->IsTrue();
373
374
  SendWrap* req_wrap;
375
  {
376
8092
    AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
377
8092
    req_wrap = new SendWrap(env, req_wrap_obj, have_callback);
378
  }
379
8092
  size_t msg_size = 0;
380
381
16184
  MaybeStackBuffer<uv_buf_t, 16> bufs(count);
382
383
  // construct uv_buf_t array
384
20139
  for (size_t i = 0; i < count; i++) {
385
36141
    Local<Value> chunk = chunks->Get(env->context(), i).ToLocalChecked();
386
387
12047
    size_t length = Buffer::Length(chunk);
388
389
12047
    bufs[i] = uv_buf_init(Buffer::Data(chunk), length);
390
12047
    msg_size += length;
391
  }
392
393
8092
  req_wrap->msg_size = msg_size;
394
395
  struct sockaddr_storage addr_storage;
396
8092
  int err = sockaddr_for_family(family, address.out(), port, &addr_storage);
397
8092
  if (err == 0) {
398
    err = req_wrap->Dispatch(uv_udp_send,
399
                             &wrap->handle_,
400
                             *bufs,
401
                             count,
402
                             reinterpret_cast<const sockaddr*>(&addr_storage),
403
8092
                             OnSend);
404
  }
405
406
8092
  if (err)
407
    delete req_wrap;
408
409
24276
  args.GetReturnValue().Set(err);
410
}
411
412
413
8086
void UDPWrap::Send(const FunctionCallbackInfo<Value>& args) {
414
8086
  DoSend(args, AF_INET);
415
8086
}
416
417
418
6
void UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) {
419
6
  DoSend(args, AF_INET6);
420
6
}
421
422
423
121
void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) {
424
  UDPWrap* wrap;
425
242
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
426
                          args.Holder(),
427
                          args.GetReturnValue().Set(UV_EBADF));
428
121
  int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
429
  // UV_EALREADY means that the socket is already bound but that's okay
430
121
  if (err == UV_EALREADY)
431
    err = 0;
432
242
  args.GetReturnValue().Set(err);
433
}
434
435
436
106
void UDPWrap::RecvStop(const FunctionCallbackInfo<Value>& args) {
437
  UDPWrap* wrap;
438
212
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
439
                          args.Holder(),
440
                          args.GetReturnValue().Set(UV_EBADF));
441
106
  int r = uv_udp_recv_stop(&wrap->handle_);
442
212
  args.GetReturnValue().Set(r);
443
}
444
445
446
8088
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
447
8088
  std::unique_ptr<SendWrap> req_wrap{static_cast<SendWrap*>(req->data)};
448
8088
  if (req_wrap->have_callback()) {
449
7931
    Environment* env = req_wrap->env();
450
7931
    HandleScope handle_scope(env->isolate());
451
7931
    Context::Scope context_scope(env->context());
452
    Local<Value> arg[] = {
453
      Integer::New(env->isolate(), status),
454
7931
      Integer::New(env->isolate(), req_wrap->msg_size),
455
31724
    };
456
15862
    req_wrap->MakeCallback(env->oncomplete_string(), 2, arg);
457
8088
  }
458
8088
}
459
460
461
12222
void UDPWrap::OnAlloc(uv_handle_t* handle,
462
                      size_t suggested_size,
463
                      uv_buf_t* buf) {
464
12222
  UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
465
12222
  *buf = wrap->env()->AllocateManaged(suggested_size).release();
466
12222
}
467
468
12222
void UDPWrap::OnRecv(uv_udp_t* handle,
469
                     ssize_t nread,
470
                     const uv_buf_t* buf_,
471
                     const struct sockaddr* addr,
472
                     unsigned int flags) {
473
12222
  UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
474
12222
  Environment* env = wrap->env();
475
476
12222
  AllocatedBuffer buf(env, *buf_);
477

12222
  if (nread == 0 && addr == nullptr) {
478
4160
    return;
479
  }
480
481
16124
  HandleScope handle_scope(env->isolate());
482
16124
  Context::Scope context_scope(env->context());
483
484
8062
  Local<Object> wrap_obj = wrap->object();
485
  Local<Value> argv[] = {
486
    Integer::New(env->isolate(), nread),
487
    wrap_obj,
488
    Undefined(env->isolate()),
489
    Undefined(env->isolate())
490
40310
  };
491
492
8062
  if (nread < 0) {
493
    wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
494
    return;
495
  }
496
497
8062
  buf.Resize(nread);
498
16124
  argv[2] = buf.ToBuffer().ToLocalChecked();
499
16124
  argv[3] = AddressToJS(env, addr);
500
16124
  wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
501
}
502
503
24
MaybeLocal<Object> UDPWrap::Instantiate(Environment* env,
504
                                        AsyncWrap* parent,
505
                                        UDPWrap::SocketType type) {
506
24
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent);
507
508
  // If this assert fires then Initialize hasn't been called yet.
509
48
  CHECK_EQ(env->udp_constructor_function().IsEmpty(), false);
510
48
  return env->udp_constructor_function()->NewInstance(env->context());
511
}
512
513
514
}  // namespace node
515
516
4282
NODE_MODULE_CONTEXT_AWARE_INTERNAL(udp_wrap, node::UDPWrap::Initialize)