GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/js_udp_wrap.cc Lines: 1 109 0.9 %
Date: 2020-07-19 22:14:24 Branches: 2 80 2.5 %

Line Branch Exec Source
1
#include "udp_wrap.h"
2
#include "async_wrap-inl.h"
3
#include "node_errors.h"
4
#include "node_sockaddr-inl.h"
5
6
#include <algorithm>
7
8
namespace node {
9
10
using errors::TryCatchScope;
11
using v8::Array;
12
using v8::Context;
13
using v8::FunctionCallbackInfo;
14
using v8::FunctionTemplate;
15
using v8::HandleScope;
16
using v8::Int32;
17
using v8::Local;
18
using v8::Object;
19
using v8::String;
20
using v8::Value;
21
22
// JSUDPWrap is a testing utility used by test/common/udppair.js
23
// to simulate UDP traffic deterministically in Node.js tests.
24
class JSUDPWrap final : public UDPWrapBase, public AsyncWrap {
25
 public:
26
  JSUDPWrap(Environment* env, Local<Object> obj);
27
28
  int RecvStart() override;
29
  int RecvStop() override;
30
  ssize_t Send(uv_buf_t* bufs,
31
               size_t nbufs,
32
               const sockaddr* addr) override;
33
  SocketAddress GetPeerName() override;
34
  SocketAddress GetSockName() override;
35
  AsyncWrap* GetAsyncWrap() override { return this; }
36
37
  static void New(const FunctionCallbackInfo<Value>& args);
38
  static void EmitReceived(const FunctionCallbackInfo<Value>& args);
39
  static void OnSendDone(const FunctionCallbackInfo<Value>& args);
40
  static void OnAfterBind(const FunctionCallbackInfo<Value>& args);
41
42
  static void Initialize(Local<Object> target,
43
                         Local<Value> unused,
44
                         Local<Context> context,
45
                         void* priv);
46
  SET_NO_MEMORY_INFO()
47
  SET_MEMORY_INFO_NAME(JSUDPWrap)
48
  SET_SELF_SIZE(JSUDPWrap)
49
};
50
51
JSUDPWrap::JSUDPWrap(Environment* env, Local<Object> obj)
52
  : AsyncWrap(env, obj, PROVIDER_JSUDPWRAP) {
53
  MakeWeak();
54
55
  obj->SetAlignedPointerInInternalField(
56
      kUDPWrapBaseField, static_cast<UDPWrapBase*>(this));
57
}
58
59
int JSUDPWrap::RecvStart() {
60
  HandleScope scope(env()->isolate());
61
  Context::Scope context_scope(env()->context());
62
  TryCatchScope try_catch(env());
63
  Local<Value> value;
64
  int32_t value_int = UV_EPROTO;
65
  if (!MakeCallback(env()->onreadstart_string(), 0, nullptr).ToLocal(&value) ||
66
      !value->Int32Value(env()->context()).To(&value_int)) {
67
    if (try_catch.HasCaught() && !try_catch.HasTerminated())
68
      errors::TriggerUncaughtException(env()->isolate(), try_catch);
69
  }
70
  return value_int;
71
}
72
73
int JSUDPWrap::RecvStop() {
74
  HandleScope scope(env()->isolate());
75
  Context::Scope context_scope(env()->context());
76
  TryCatchScope try_catch(env());
77
  Local<Value> value;
78
  int32_t value_int = UV_EPROTO;
79
  if (!MakeCallback(env()->onreadstop_string(), 0, nullptr).ToLocal(&value) ||
80
      !value->Int32Value(env()->context()).To(&value_int)) {
81
    if (try_catch.HasCaught() && !try_catch.HasTerminated())
82
      errors::TriggerUncaughtException(env()->isolate(), try_catch);
83
  }
84
  return value_int;
85
}
86
87
ssize_t JSUDPWrap::Send(uv_buf_t* bufs,
88
                        size_t nbufs,
89
                        const sockaddr* addr) {
90
  HandleScope scope(env()->isolate());
91
  Context::Scope context_scope(env()->context());
92
  TryCatchScope try_catch(env());
93
  Local<Value> value;
94
  int64_t value_int = UV_EPROTO;
95
  size_t total_len = 0;
96
97
  MaybeStackBuffer<Local<Value>, 16> buffers(nbufs);
98
  for (size_t i = 0; i < nbufs; i++) {
99
    buffers[i] = Buffer::Copy(env(), bufs[i].base, bufs[i].len)
100
        .ToLocalChecked();
101
    total_len += bufs[i].len;
102
  }
103
104
  Local<Value> args[] = {
105
    listener()->CreateSendWrap(total_len)->object(),
106
    Array::New(env()->isolate(), buffers.out(), nbufs),
107
    AddressToJS(env(), addr)
108
  };
109
110
  if (!MakeCallback(env()->onwrite_string(), arraysize(args), args)
111
          .ToLocal(&value) ||
112
      !value->IntegerValue(env()->context()).To(&value_int)) {
113
    if (try_catch.HasCaught() && !try_catch.HasTerminated())
114
      errors::TriggerUncaughtException(env()->isolate(), try_catch);
115
  }
116
  return value_int;
117
}
118
119
SocketAddress JSUDPWrap::GetPeerName() {
120
  SocketAddress ret;
121
  CHECK(SocketAddress::New(AF_INET, "127.0.0.1", 1337, &ret));
122
  return ret;
123
}
124
125
SocketAddress JSUDPWrap::GetSockName() {
126
  SocketAddress ret;
127
  CHECK(SocketAddress::New(AF_INET, "127.0.0.1", 1337, &ret));
128
  return ret;
129
}
130
131
void JSUDPWrap::New(const FunctionCallbackInfo<Value>& args) {
132
  Environment* env = Environment::GetCurrent(args);
133
  CHECK(args.IsConstructCall());
134
  new JSUDPWrap(env, args.Holder());
135
}
136
137
void JSUDPWrap::EmitReceived(const FunctionCallbackInfo<Value>& args) {
138
  JSUDPWrap* wrap;
139
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
140
  Environment* env = wrap->env();
141
142
  ArrayBufferViewContents<char> buffer(args[0]);
143
  const char* data = buffer.data();
144
  int len = buffer.length();
145
146
  CHECK(args[1]->IsInt32());   // family
147
  CHECK(args[2]->IsString());  // address
148
  CHECK(args[3]->IsInt32());   // port
149
  CHECK(args[4]->IsInt32());   // flags
150
  int family = args[1].As<Int32>()->Value() == 4 ? AF_INET : AF_INET6;
151
  Utf8Value address(env->isolate(), args[2]);
152
  int port = args[3].As<Int32>()->Value();
153
  int flags = args[3].As<Int32>()->Value();
154
155
  sockaddr_storage addr;
156
  CHECK_EQ(sockaddr_for_family(family, *address, port, &addr), 0);
157
158
  // Repeatedly ask the stream's owner for memory, copy the data that we
159
  // just read from JS into those buffers and emit them as reads.
160
  while (len != 0) {
161
    uv_buf_t buf = wrap->listener()->OnAlloc(len);
162
    ssize_t avail = std::min<size_t>(buf.len, len);
163
    memcpy(buf.base, data, avail);
164
    data += avail;
165
    len -= avail;
166
    wrap->listener()->OnRecv(
167
        avail, buf, reinterpret_cast<sockaddr*>(&addr), flags);
168
  }
169
}
170
171
void JSUDPWrap::OnSendDone(const FunctionCallbackInfo<Value>& args) {
172
  JSUDPWrap* wrap;
173
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
174
175
  CHECK(args[0]->IsObject());
176
  CHECK(args[1]->IsInt32());
177
  ReqWrap<uv_udp_send_t>* req_wrap;
178
  ASSIGN_OR_RETURN_UNWRAP(&req_wrap, args[0].As<Object>());
179
  int status = args[1].As<Int32>()->Value();
180
181
  wrap->listener()->OnSendDone(req_wrap, status);
182
}
183
184
void JSUDPWrap::OnAfterBind(const FunctionCallbackInfo<Value>& args) {
185
  JSUDPWrap* wrap;
186
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
187
188
  wrap->listener()->OnAfterBind();
189
}
190
191
void JSUDPWrap::Initialize(Local<Object> target,
192
                           Local<Value> unused,
193
                           Local<Context> context,
194
                           void* priv) {
195
  Environment* env = Environment::GetCurrent(context);
196
197
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
198
  Local<String> js_udp_wrap_string =
199
      FIXED_ONE_BYTE_STRING(env->isolate(), "JSUDPWrap");
200
  t->SetClassName(js_udp_wrap_string);
201
  t->InstanceTemplate()
202
    ->SetInternalFieldCount(UDPWrapBase::kUDPWrapBaseField + 1);
203
  t->Inherit(AsyncWrap::GetConstructorTemplate(env));
204
205
  UDPWrapBase::AddMethods(env, t);
206
  env->SetProtoMethod(t, "emitReceived", EmitReceived);
207
  env->SetProtoMethod(t, "onSendDone", OnSendDone);
208
  env->SetProtoMethod(t, "onAfterBind", OnAfterBind);
209
210
  target->Set(env->context(),
211
              js_udp_wrap_string,
212
              t->GetFunction(context).ToLocalChecked()).Check();
213
}
214
215
216
}  // namespace node
217
218

19959
NODE_MODULE_CONTEXT_AWARE_INTERNAL(js_udp_wrap, node::JSUDPWrap::Initialize)