GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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::DontDelete; |
||
34 |
using v8::FunctionCallbackInfo; |
||
35 |
using v8::FunctionTemplate; |
||
36 |
using v8::HandleScope; |
||
37 |
using v8::Integer; |
||
38 |
using v8::Local; |
||
39 |
using v8::MaybeLocal; |
||
40 |
using v8::Object; |
||
41 |
using v8::PropertyAttribute; |
||
42 |
using v8::ReadOnly; |
||
43 |
using v8::Signature; |
||
44 |
using v8::String; |
||
45 |
using v8::Uint32; |
||
46 |
using v8::Undefined; |
||
47 |
using v8::Value; |
||
48 |
|||
49 |
✗✓ | 4 |
class SendWrap : public ReqWrap<uv_udp_send_t> { |
50 |
public: |
||
51 |
SendWrap(Environment* env, Local<Object> req_wrap_obj, bool have_callback); |
||
52 |
inline bool have_callback() const; |
||
53 |
size_t msg_size; |
||
54 |
|||
55 |
1 |
SET_NO_MEMORY_INFO() |
|
56 |
1 |
SET_MEMORY_INFO_NAME(SendWrap) |
|
57 |
1 |
SET_SELF_SIZE(SendWrap) |
|
58 |
|||
59 |
private: |
||
60 |
const bool have_callback_; |
||
61 |
}; |
||
62 |
|||
63 |
|||
64 |
2 |
SendWrap::SendWrap(Environment* env, |
|
65 |
Local<Object> req_wrap_obj, |
||
66 |
bool have_callback) |
||
67 |
: ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_UDPSENDWRAP), |
||
68 |
2 |
have_callback_(have_callback) { |
|
69 |
2 |
} |
|
70 |
|||
71 |
|||
72 |
2 |
inline bool SendWrap::have_callback() const { |
|
73 |
2 |
return have_callback_; |
|
74 |
} |
||
75 |
|||
76 |
|||
77 |
242 |
UDPWrap::UDPWrap(Environment* env, Local<Object> object) |
|
78 |
: HandleWrap(env, |
||
79 |
object, |
||
80 |
reinterpret_cast<uv_handle_t*>(&handle_), |
||
81 |
242 |
AsyncWrap::PROVIDER_UDPWRAP) { |
|
82 |
242 |
int r = uv_udp_init(env->event_loop(), &handle_); |
|
83 |
✗✓ | 242 |
CHECK_EQ(r, 0); // can't fail anyway |
84 |
242 |
} |
|
85 |
|||
86 |
|||
87 |
4360 |
void UDPWrap::Initialize(Local<Object> target, |
|
88 |
Local<Value> unused, |
||
89 |
Local<Context> context, |
||
90 |
void* priv) { |
||
91 |
4360 |
Environment* env = Environment::GetCurrent(context); |
|
92 |
|||
93 |
4360 |
Local<FunctionTemplate> t = env->NewFunctionTemplate(New); |
|
94 |
8720 |
t->InstanceTemplate()->SetInternalFieldCount(1); |
|
95 |
Local<String> udpString = |
||
96 |
4360 |
FIXED_ONE_BYTE_STRING(env->isolate(), "UDP"); |
|
97 |
4360 |
t->SetClassName(udpString); |
|
98 |
|||
99 |
enum PropertyAttribute attributes = |
||
100 |
4360 |
static_cast<PropertyAttribute>(ReadOnly | DontDelete); |
|
101 |
|||
102 |
4360 |
Local<Signature> signature = Signature::New(env->isolate(), t); |
|
103 |
|||
104 |
Local<FunctionTemplate> get_fd_templ = |
||
105 |
FunctionTemplate::New(env->isolate(), |
||
106 |
UDPWrap::GetFD, |
||
107 |
env->as_callback_data(), |
||
108 |
8720 |
signature); |
|
109 |
|||
110 |
13080 |
t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(), |
|
111 |
get_fd_templ, |
||
112 |
Local<FunctionTemplate>(), |
||
113 |
13080 |
attributes); |
|
114 |
|||
115 |
4360 |
env->SetProtoMethod(t, "open", Open); |
|
116 |
4360 |
env->SetProtoMethod(t, "bind", Bind); |
|
117 |
4360 |
env->SetProtoMethod(t, "connect", Connect); |
|
118 |
4360 |
env->SetProtoMethod(t, "send", Send); |
|
119 |
4360 |
env->SetProtoMethod(t, "bind6", Bind6); |
|
120 |
4360 |
env->SetProtoMethod(t, "connect6", Connect6); |
|
121 |
4360 |
env->SetProtoMethod(t, "send6", Send6); |
|
122 |
4360 |
env->SetProtoMethod(t, "disconnect", Disconnect); |
|
123 |
4360 |
env->SetProtoMethod(t, "recvStart", RecvStart); |
|
124 |
4360 |
env->SetProtoMethod(t, "recvStop", RecvStop); |
|
125 |
env->SetProtoMethod(t, "getpeername", |
||
126 |
4360 |
GetSockOrPeerName<UDPWrap, uv_udp_getpeername>); |
|
127 |
env->SetProtoMethod(t, "getsockname", |
||
128 |
4360 |
GetSockOrPeerName<UDPWrap, uv_udp_getsockname>); |
|
129 |
4360 |
env->SetProtoMethod(t, "addMembership", AddMembership); |
|
130 |
4360 |
env->SetProtoMethod(t, "dropMembership", DropMembership); |
|
131 |
4360 |
env->SetProtoMethod(t, "setMulticastInterface", SetMulticastInterface); |
|
132 |
4360 |
env->SetProtoMethod(t, "setMulticastTTL", SetMulticastTTL); |
|
133 |
4360 |
env->SetProtoMethod(t, "setMulticastLoopback", SetMulticastLoopback); |
|
134 |
4360 |
env->SetProtoMethod(t, "setBroadcast", SetBroadcast); |
|
135 |
4360 |
env->SetProtoMethod(t, "setTTL", SetTTL); |
|
136 |
4360 |
env->SetProtoMethod(t, "bufferSize", BufferSize); |
|
137 |
|||
138 |
8720 |
t->Inherit(HandleWrap::GetConstructorTemplate(env)); |
|
139 |
|||
140 |
target->Set(env->context(), |
||
141 |
udpString, |
||
142 |
21800 |
t->GetFunction(env->context()).ToLocalChecked()).Check(); |
|
143 |
env->set_udp_constructor_function( |
||
144 |
13080 |
t->GetFunction(env->context()).ToLocalChecked()); |
|
145 |
|||
146 |
// Create FunctionTemplate for SendWrap |
||
147 |
Local<FunctionTemplate> swt = |
||
148 |
4360 |
BaseObject::MakeLazilyInitializedJSTemplate(env); |
|
149 |
8720 |
swt->Inherit(AsyncWrap::GetConstructorTemplate(env)); |
|
150 |
Local<String> sendWrapString = |
||
151 |
4360 |
FIXED_ONE_BYTE_STRING(env->isolate(), "SendWrap"); |
|
152 |
4360 |
swt->SetClassName(sendWrapString); |
|
153 |
target->Set(env->context(), |
||
154 |
sendWrapString, |
||
155 |
21800 |
swt->GetFunction(env->context()).ToLocalChecked()).Check(); |
|
156 |
|||
157 |
4360 |
Local<Object> constants = Object::New(env->isolate()); |
|
158 |
17440 |
NODE_DEFINE_CONSTANT(constants, UV_UDP_IPV6ONLY); |
|
159 |
target->Set(context, |
||
160 |
env->constants_string(), |
||
161 |
13080 |
constants).Check(); |
|
162 |
4360 |
} |
|
163 |
|||
164 |
|||
165 |
242 |
void UDPWrap::New(const FunctionCallbackInfo<Value>& args) { |
|
166 |
✗✓ | 242 |
CHECK(args.IsConstructCall()); |
167 |
242 |
Environment* env = Environment::GetCurrent(args); |
|
168 |
242 |
new UDPWrap(env, args.This()); |
|
169 |
242 |
} |
|
170 |
|||
171 |
|||
172 |
21 |
void UDPWrap::GetFD(const FunctionCallbackInfo<Value>& args) { |
|
173 |
21 |
int fd = UV_EBADF; |
|
174 |
#if !defined(_WIN32) |
||
175 |
21 |
UDPWrap* wrap = Unwrap<UDPWrap>(args.This()); |
|
176 |
✓✓ | 21 |
if (wrap != nullptr) |
177 |
20 |
uv_fileno(reinterpret_cast<uv_handle_t*>(&wrap->handle_), &fd); |
|
178 |
#endif |
||
179 |
63 |
args.GetReturnValue().Set(fd); |
|
180 |
21 |
} |
|
181 |
|||
182 |
7278 |
int sockaddr_for_family(int address_family, |
|
183 |
const char* address, |
||
184 |
const unsigned short port, |
||
185 |
struct sockaddr_storage* addr) { |
||
186 |
✓✓✗ | 7278 |
switch (address_family) { |
187 |
case AF_INET: |
||
188 |
7261 |
return uv_ip4_addr(address, port, reinterpret_cast<sockaddr_in*>(addr)); |
|
189 |
case AF_INET6: |
||
190 |
17 |
return uv_ip6_addr(address, port, reinterpret_cast<sockaddr_in6*>(addr)); |
|
191 |
default: |
||
192 |
CHECK(0 && "unexpected address family"); |
||
193 |
} |
||
194 |
} |
||
195 |
|||
196 |
135 |
void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) { |
|
197 |
UDPWrap* wrap; |
||
198 |
✗✓ | 135 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
199 |
args.Holder(), |
||
200 |
args.GetReturnValue().Set(UV_EBADF)); |
||
201 |
|||
202 |
// bind(ip, port, flags) |
||
203 |
✗✓ | 135 |
CHECK_EQ(args.Length(), 3); |
204 |
|||
205 |
135 |
node::Utf8Value address(args.GetIsolate(), args[0]); |
|
206 |
135 |
Local<Context> ctx = args.GetIsolate()->GetCurrentContext(); |
|
207 |
uint32_t port, flags; |
||
208 |
✓✗✗✓ ✓✗✓✗ ✗✓ |
945 |
if (!args[1]->Uint32Value(ctx).To(&port) || |
209 |
✓✗✓✗ |
540 |
!args[2]->Uint32Value(ctx).To(&flags)) |
210 |
return; |
||
211 |
struct sockaddr_storage addr_storage; |
||
212 |
135 |
int err = sockaddr_for_family(family, address.out(), port, &addr_storage); |
|
213 |
✓✓ | 135 |
if (err == 0) { |
214 |
err = uv_udp_bind(&wrap->handle_, |
||
215 |
reinterpret_cast<const sockaddr*>(&addr_storage), |
||
216 |
134 |
flags); |
|
217 |
} |
||
218 |
|||
219 |
✓✗ | 270 |
args.GetReturnValue().Set(err); |
220 |
} |
||
221 |
|||
222 |
|||
223 |
14 |
void UDPWrap::DoConnect(const FunctionCallbackInfo<Value>& args, int family) { |
|
224 |
UDPWrap* wrap; |
||
225 |
✗✓ | 14 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
226 |
args.Holder(), |
||
227 |
args.GetReturnValue().Set(UV_EBADF)); |
||
228 |
|||
229 |
✗✓ | 14 |
CHECK_EQ(args.Length(), 2); |
230 |
|||
231 |
14 |
node::Utf8Value address(args.GetIsolate(), args[0]); |
|
232 |
14 |
Local<Context> ctx = args.GetIsolate()->GetCurrentContext(); |
|
233 |
uint32_t port; |
||
234 |
✗✓ | 42 |
if (!args[1]->Uint32Value(ctx).To(&port)) |
235 |
return; |
||
236 |
struct sockaddr_storage addr_storage; |
||
237 |
14 |
int err = sockaddr_for_family(family, address.out(), port, &addr_storage); |
|
238 |
✓✗ | 14 |
if (err == 0) { |
239 |
err = uv_udp_connect(&wrap->handle_, |
||
240 |
14 |
reinterpret_cast<const sockaddr*>(&addr_storage)); |
|
241 |
} |
||
242 |
|||
243 |
✓✗ | 28 |
args.GetReturnValue().Set(err); |
244 |
} |
||
245 |
|||
246 |
|||
247 |
6 |
void UDPWrap::Open(const FunctionCallbackInfo<Value>& args) { |
|
248 |
UDPWrap* wrap; |
||
249 |
✗✓ | 12 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
250 |
args.Holder(), |
||
251 |
args.GetReturnValue().Set(UV_EBADF)); |
||
252 |
✗✓ | 12 |
CHECK(args[0]->IsNumber()); |
253 |
18 |
int fd = static_cast<int>(args[0].As<Integer>()->Value()); |
|
254 |
6 |
int err = uv_udp_open(&wrap->handle_, fd); |
|
255 |
|||
256 |
12 |
args.GetReturnValue().Set(err); |
|
257 |
} |
||
258 |
|||
259 |
|||
260 |
124 |
void UDPWrap::Bind(const FunctionCallbackInfo<Value>& args) { |
|
261 |
124 |
DoBind(args, AF_INET); |
|
262 |
124 |
} |
|
263 |
|||
264 |
|||
265 |
11 |
void UDPWrap::Bind6(const FunctionCallbackInfo<Value>& args) { |
|
266 |
11 |
DoBind(args, AF_INET6); |
|
267 |
11 |
} |
|
268 |
|||
269 |
|||
270 |
30 |
void UDPWrap::BufferSize(const FunctionCallbackInfo<Value>& args) { |
|
271 |
30 |
Environment* env = Environment::GetCurrent(args); |
|
272 |
UDPWrap* wrap; |
||
273 |
✗✓ | 36 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
274 |
args.Holder(), |
||
275 |
args.GetReturnValue().Set(UV_EBADF)); |
||
276 |
|||
277 |
✗✓ | 60 |
CHECK(args[0]->IsUint32()); |
278 |
✗✓ | 60 |
CHECK(args[1]->IsBoolean()); |
279 |
90 |
bool is_recv = args[1].As<v8::Boolean>()->Value(); |
|
280 |
const char* uv_func_name = is_recv ? "uv_recv_buffer_size" : |
||
281 |
✓✓ | 30 |
"uv_send_buffer_size"; |
282 |
|||
283 |
✓✓ | 60 |
if (!args[0]->IsInt32()) { |
284 |
2 |
env->CollectUVExceptionInfo(args[2], UV_EINVAL, uv_func_name); |
|
285 |
4 |
return args.GetReturnValue().SetUndefined(); |
|
286 |
} |
||
287 |
|||
288 |
28 |
uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&wrap->handle_); |
|
289 |
84 |
int size = static_cast<int>(args[0].As<Uint32>()->Value()); |
|
290 |
int err; |
||
291 |
|||
292 |
✓✓ | 28 |
if (is_recv) |
293 |
15 |
err = uv_recv_buffer_size(handle, &size); |
|
294 |
else |
||
295 |
13 |
err = uv_send_buffer_size(handle, &size); |
|
296 |
|||
297 |
✓✓ | 28 |
if (err != 0) { |
298 |
4 |
env->CollectUVExceptionInfo(args[2], err, uv_func_name); |
|
299 |
8 |
return args.GetReturnValue().SetUndefined(); |
|
300 |
} |
||
301 |
|||
302 |
72 |
args.GetReturnValue().Set(size); |
|
303 |
} |
||
304 |
|||
305 |
|||
306 |
14 |
void UDPWrap::Connect(const FunctionCallbackInfo<Value>& args) { |
|
307 |
14 |
DoConnect(args, AF_INET); |
|
308 |
14 |
} |
|
309 |
|||
310 |
|||
311 |
void UDPWrap::Connect6(const FunctionCallbackInfo<Value>& args) { |
||
312 |
DoConnect(args, AF_INET6); |
||
313 |
} |
||
314 |
|||
315 |
|||
316 |
1 |
void UDPWrap::Disconnect(const FunctionCallbackInfo<Value>& args) { |
|
317 |
UDPWrap* wrap; |
||
318 |
✗✓ | 2 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
319 |
args.Holder(), |
||
320 |
args.GetReturnValue().Set(UV_EBADF)); |
||
321 |
|||
322 |
✗✓ | 1 |
CHECK_EQ(args.Length(), 0); |
323 |
|||
324 |
1 |
int err = uv_udp_connect(&wrap->handle_, nullptr); |
|
325 |
|||
326 |
2 |
args.GetReturnValue().Set(err); |
|
327 |
} |
||
328 |
|||
329 |
#define X(name, fn) \ |
||
330 |
void UDPWrap::name(const FunctionCallbackInfo<Value>& args) { \ |
||
331 |
UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); \ |
||
332 |
Environment* env = wrap->env(); \ |
||
333 |
CHECK_EQ(args.Length(), 1); \ |
||
334 |
int flag; \ |
||
335 |
if (!args[0]->Int32Value(env->context()).To(&flag)) { \ |
||
336 |
return; \ |
||
337 |
} \ |
||
338 |
int err = wrap == nullptr ? UV_EBADF : fn(&wrap->handle_, flag); \ |
||
339 |
args.GetReturnValue().Set(err); \ |
||
340 |
} |
||
341 |
|||
342 |
✗✓✗✓ ✓✗ |
24 |
X(SetTTL, uv_udp_set_ttl) |
343 |
✗✓✗✓ ✓✗ |
40 |
X(SetBroadcast, uv_udp_set_broadcast) |
344 |
✗✓✗✓ ✓✗ |
24 |
X(SetMulticastTTL, uv_udp_set_multicast_ttl) |
345 |
✗✓✗✓ ✓✗ |
32 |
X(SetMulticastLoopback, uv_udp_set_multicast_loop) |
346 |
|||
347 |
#undef X |
||
348 |
|||
349 |
9 |
void UDPWrap::SetMulticastInterface(const FunctionCallbackInfo<Value>& args) { |
|
350 |
UDPWrap* wrap; |
||
351 |
✗✓ | 18 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
352 |
args.Holder(), |
||
353 |
args.GetReturnValue().Set(UV_EBADF)); |
||
354 |
|||
355 |
✗✓ | 9 |
CHECK_EQ(args.Length(), 1); |
356 |
✗✓ | 27 |
CHECK(args[0]->IsString()); |
357 |
|||
358 |
9 |
Utf8Value iface(args.GetIsolate(), args[0]); |
|
359 |
|||
360 |
9 |
const char* iface_cstr = *iface; |
|
361 |
|||
362 |
9 |
int err = uv_udp_set_multicast_interface(&wrap->handle_, iface_cstr); |
|
363 |
18 |
args.GetReturnValue().Set(err); |
|
364 |
} |
||
365 |
|||
366 |
6 |
void UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args, |
|
367 |
uv_membership membership) { |
||
368 |
UDPWrap* wrap; |
||
369 |
✗✓ | 12 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
370 |
args.Holder(), |
||
371 |
args.GetReturnValue().Set(UV_EBADF)); |
||
372 |
|||
373 |
✗✓ | 6 |
CHECK_EQ(args.Length(), 2); |
374 |
|||
375 |
6 |
node::Utf8Value address(args.GetIsolate(), args[0]); |
|
376 |
12 |
node::Utf8Value iface(args.GetIsolate(), args[1]); |
|
377 |
|||
378 |
6 |
const char* iface_cstr = *iface; |
|
379 |
✗✓✗✗ ✗✓✓✗ ✓✗ |
24 |
if (args[1]->IsUndefined() || args[1]->IsNull()) { |
380 |
6 |
iface_cstr = nullptr; |
|
381 |
} |
||
382 |
|||
383 |
int err = uv_udp_set_membership(&wrap->handle_, |
||
384 |
6 |
*address, |
|
385 |
iface_cstr, |
||
386 |
6 |
membership); |
|
387 |
18 |
args.GetReturnValue().Set(err); |
|
388 |
} |
||
389 |
|||
390 |
|||
391 |
3 |
void UDPWrap::AddMembership(const FunctionCallbackInfo<Value>& args) { |
|
392 |
3 |
SetMembership(args, UV_JOIN_GROUP); |
|
393 |
3 |
} |
|
394 |
|||
395 |
|||
396 |
3 |
void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) { |
|
397 |
3 |
SetMembership(args, UV_LEAVE_GROUP); |
|
398 |
3 |
} |
|
399 |
|||
400 |
|||
401 |
7145 |
void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) { |
|
402 |
7145 |
Environment* env = Environment::GetCurrent(args); |
|
403 |
|||
404 |
UDPWrap* wrap; |
||
405 |
✗✓ | 14287 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
406 |
args.Holder(), |
||
407 |
args.GetReturnValue().Set(UV_EBADF)); |
||
408 |
|||
409 |
✓✓✗✓ ✗✓ |
14274 |
CHECK(args.Length() == 4 || args.Length() == 6); |
410 |
✗✓ | 14290 |
CHECK(args[0]->IsObject()); |
411 |
✗✓ | 14290 |
CHECK(args[1]->IsArray()); |
412 |
✗✓ | 14290 |
CHECK(args[2]->IsUint32()); |
413 |
|||
414 |
7145 |
bool sendto = args.Length() == 6; |
|
415 |
✓✓ | 7145 |
if (sendto) { |
416 |
// send(req, list, list.length, port, address, hasCallback) |
||
417 |
✗✓ | 14258 |
CHECK(args[3]->IsUint32()); |
418 |
✗✓ | 21387 |
CHECK(args[4]->IsString()); |
419 |
✗✓ | 14258 |
CHECK(args[5]->IsBoolean()); |
420 |
} else { |
||
421 |
// send(req, list, list.length, hasCallback) |
||
422 |
✗✓ | 32 |
CHECK(args[3]->IsBoolean()); |
423 |
} |
||
424 |
|||
425 |
14290 |
Local<Object> req_wrap_obj = args[0].As<Object>(); |
|
426 |
14290 |
Local<Array> chunks = args[1].As<Array>(); |
|
427 |
// it is faster to fetch the length of the |
||
428 |
// array in js-land |
||
429 |
21435 |
size_t count = args[2].As<Uint32>()->Value(); |
|
430 |
✓✓✓✓ ✓✓ |
21435 |
const bool have_callback = sendto ? args[5]->IsTrue() : args[3]->IsTrue(); |
431 |
|||
432 |
7145 |
size_t msg_size = 0; |
|
433 |
|||
434 |
7145 |
MaybeStackBuffer<uv_buf_t, 16> bufs(count); |
|
435 |
|||
436 |
// construct uv_buf_t array |
||
437 |
✓✓ | 17887 |
for (size_t i = 0; i < count; i++) { |
438 |
32226 |
Local<Value> chunk = chunks->Get(env->context(), i).ToLocalChecked(); |
|
439 |
|||
440 |
10742 |
size_t length = Buffer::Length(chunk); |
|
441 |
|||
442 |
10742 |
bufs[i] = uv_buf_init(Buffer::Data(chunk), length); |
|
443 |
10742 |
msg_size += length; |
|
444 |
} |
||
445 |
|||
446 |
7145 |
int err = 0; |
|
447 |
struct sockaddr_storage addr_storage; |
||
448 |
7145 |
sockaddr* addr = nullptr; |
|
449 |
✓✓ | 7145 |
if (sendto) { |
450 |
21387 |
const unsigned short port = args[3].As<Uint32>()->Value(); |
|
451 |
7129 |
node::Utf8Value address(env->isolate(), args[4]); |
|
452 |
7129 |
err = sockaddr_for_family(family, address.out(), port, &addr_storage); |
|
453 |
✓✗ | 7129 |
if (err == 0) { |
454 |
7129 |
addr = reinterpret_cast<sockaddr*>(&addr_storage); |
|
455 |
7129 |
} |
|
456 |
} |
||
457 |
|||
458 |
7145 |
uv_buf_t* bufs_ptr = *bufs; |
|
459 |
✓✗✓✓ ✓✗✓✓ |
7145 |
if (err == 0 && !UNLIKELY(env->options()->test_udp_no_try_send)) { |
460 |
7143 |
err = uv_udp_try_send(&wrap->handle_, bufs_ptr, count, addr); |
|
461 |
✓✗✗✓ |
7143 |
if (err == UV_ENOSYS || err == UV_EAGAIN) { |
462 |
err = 0; |
||
463 |
✓✓ | 7143 |
} else if (err >= 0) { |
464 |
7142 |
size_t sent = err; |
|
465 |
✓✓✓✗ |
25023 |
while (count > 0 && bufs_ptr->len <= sent) { |
466 |
10739 |
sent -= bufs_ptr->len; |
|
467 |
10739 |
bufs_ptr++; |
|
468 |
10739 |
count--; |
|
469 |
} |
||
470 |
✗✓ | 7142 |
if (count > 0) { |
471 |
CHECK_LT(sent, bufs_ptr->len); |
||
472 |
bufs_ptr->base += sent; |
||
473 |
bufs_ptr->len -= sent; |
||
474 |
} else { |
||
475 |
✗✓ | 7142 |
CHECK_EQ(static_cast<size_t>(err), msg_size); |
476 |
// + 1 so that the JS side can distinguish 0-length async sends from |
||
477 |
// 0-length sync sends. |
||
478 |
21426 |
args.GetReturnValue().Set(static_cast<uint32_t>(msg_size) + 1); |
|
479 |
7142 |
return; |
|
480 |
} |
||
481 |
} |
||
482 |
} |
||
483 |
|||
484 |
✓✓ | 3 |
if (err == 0) { |
485 |
2 |
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap); |
|
486 |
2 |
SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback); |
|
487 |
2 |
req_wrap->msg_size = msg_size; |
|
488 |
|||
489 |
err = req_wrap->Dispatch(uv_udp_send, |
||
490 |
&wrap->handle_, |
||
491 |
bufs_ptr, |
||
492 |
count, |
||
493 |
addr, |
||
494 |
2 |
OnSend); |
|
495 |
✗✓ | 2 |
if (err) |
496 |
delete req_wrap; |
||
497 |
} |
||
498 |
|||
499 |
✓✓ | 6 |
args.GetReturnValue().Set(err); |
500 |
} |
||
501 |
|||
502 |
|||
503 |
7139 |
void UDPWrap::Send(const FunctionCallbackInfo<Value>& args) { |
|
504 |
7139 |
DoSend(args, AF_INET); |
|
505 |
7139 |
} |
|
506 |
|||
507 |
|||
508 |
6 |
void UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) { |
|
509 |
6 |
DoSend(args, AF_INET6); |
|
510 |
6 |
} |
|
511 |
|||
512 |
|||
513 |
138 |
void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) { |
|
514 |
UDPWrap* wrap; |
||
515 |
✗✓ | 276 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
516 |
args.Holder(), |
||
517 |
args.GetReturnValue().Set(UV_EBADF)); |
||
518 |
138 |
int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv); |
|
519 |
// UV_EALREADY means that the socket is already bound but that's okay |
||
520 |
✗✓ | 138 |
if (err == UV_EALREADY) |
521 |
err = 0; |
||
522 |
276 |
args.GetReturnValue().Set(err); |
|
523 |
} |
||
524 |
|||
525 |
|||
526 |
122 |
void UDPWrap::RecvStop(const FunctionCallbackInfo<Value>& args) { |
|
527 |
UDPWrap* wrap; |
||
528 |
✗✓ | 244 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, |
529 |
args.Holder(), |
||
530 |
args.GetReturnValue().Set(UV_EBADF)); |
||
531 |
122 |
int r = uv_udp_recv_stop(&wrap->handle_); |
|
532 |
244 |
args.GetReturnValue().Set(r); |
|
533 |
} |
||
534 |
|||
535 |
|||
536 |
2 |
void UDPWrap::OnSend(uv_udp_send_t* req, int status) { |
|
537 |
2 |
std::unique_ptr<SendWrap> req_wrap{static_cast<SendWrap*>(req->data)}; |
|
538 |
✓✗ | 2 |
if (req_wrap->have_callback()) { |
539 |
2 |
Environment* env = req_wrap->env(); |
|
540 |
2 |
HandleScope handle_scope(env->isolate()); |
|
541 |
2 |
Context::Scope context_scope(env->context()); |
|
542 |
Local<Value> arg[] = { |
||
543 |
Integer::New(env->isolate(), status), |
||
544 |
2 |
Integer::New(env->isolate(), req_wrap->msg_size), |
|
545 |
8 |
}; |
|
546 |
4 |
req_wrap->MakeCallback(env->oncomplete_string(), 2, arg); |
|
547 |
2 |
} |
|
548 |
2 |
} |
|
549 |
|||
550 |
|||
551 |
14132 |
void UDPWrap::OnAlloc(uv_handle_t* handle, |
|
552 |
size_t suggested_size, |
||
553 |
uv_buf_t* buf) { |
||
554 |
14132 |
UDPWrap* wrap = static_cast<UDPWrap*>(handle->data); |
|
555 |
14132 |
*buf = wrap->env()->AllocateManaged(suggested_size).release(); |
|
556 |
14132 |
} |
|
557 |
|||
558 |
14132 |
void UDPWrap::OnRecv(uv_udp_t* handle, |
|
559 |
ssize_t nread, |
||
560 |
const uv_buf_t* buf_, |
||
561 |
const struct sockaddr* addr, |
||
562 |
unsigned int flags) { |
||
563 |
14132 |
UDPWrap* wrap = static_cast<UDPWrap*>(handle->data); |
|
564 |
14132 |
Environment* env = wrap->env(); |
|
565 |
|||
566 |
14132 |
AllocatedBuffer buf(env, *buf_); |
|
567 |
✓✓✓✓ |
14132 |
if (nread == 0 && addr == nullptr) { |
568 |
7024 |
return; |
|
569 |
} |
||
570 |
|||
571 |
✓✓ | 14216 |
HandleScope handle_scope(env->isolate()); |
572 |
✓✗ | 14216 |
Context::Scope context_scope(env->context()); |
573 |
|||
574 |
7108 |
Local<Object> wrap_obj = wrap->object(); |
|
575 |
Local<Value> argv[] = { |
||
576 |
Integer::New(env->isolate(), nread), |
||
577 |
wrap_obj, |
||
578 |
Undefined(env->isolate()), |
||
579 |
Undefined(env->isolate()) |
||
580 |
35540 |
}; |
|
581 |
|||
582 |
✗✓ | 7108 |
if (nread < 0) { |
583 |
wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); |
||
584 |
return; |
||
585 |
} |
||
586 |
|||
587 |
7108 |
buf.Resize(nread); |
|
588 |
14216 |
argv[2] = buf.ToBuffer().ToLocalChecked(); |
|
589 |
14216 |
argv[3] = AddressToJS(env, addr); |
|
590 |
14216 |
wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); |
|
591 |
} |
||
592 |
|||
593 |
25 |
MaybeLocal<Object> UDPWrap::Instantiate(Environment* env, |
|
594 |
AsyncWrap* parent, |
||
595 |
UDPWrap::SocketType type) { |
||
596 |
25 |
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent); |
|
597 |
|||
598 |
// If this assert fires then Initialize hasn't been called yet. |
||
599 |
✗✓ | 50 |
CHECK_EQ(env->udp_constructor_function().IsEmpty(), false); |
600 |
50 |
return env->udp_constructor_function()->NewInstance(env->context()); |
|
601 |
} |
||
602 |
|||
603 |
|||
604 |
} // namespace node |
||
605 |
|||
606 |
4981 |
NODE_MODULE_CONTEXT_AWARE_INTERNAL(udp_wrap, node::UDPWrap::Initialize) |
Generated by: GCOVR (Version 3.4) |