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


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

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

24
X(SetTTL, uv_udp_set_ttl)
292

40
X(SetBroadcast, uv_udp_set_broadcast)
293

24
X(SetMulticastTTL, uv_udp_set_multicast_ttl)
294

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


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

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