GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/tcp_wrap.cc Lines: 170 178 95.5 %
Date: 2016-09-05 Branches: 39 79 49.4 %

Line Branch Exec Source
1
#include "tcp_wrap.h"
2
3
#include "connection_wrap.h"
4
#include "env.h"
5
#include "env-inl.h"
6
#include "handle_wrap.h"
7
#include "node_buffer.h"
8
#include "node_wrap.h"
9
#include "connect_wrap.h"
10
#include "stream_wrap.h"
11
#include "util.h"
12
#include "util-inl.h"
13
14
#include <stdlib.h>
15
16
17
namespace node {
18
19
using v8::Boolean;
20
using v8::Context;
21
using v8::EscapableHandleScope;
22
using v8::External;
23
using v8::Function;
24
using v8::FunctionCallbackInfo;
25
using v8::FunctionTemplate;
26
using v8::HandleScope;
27
using v8::Integer;
28
using v8::Local;
29
using v8::Object;
30
using v8::String;
31
using v8::Value;
32
33
34
3297
Local<Object> TCPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
35
6594
  EscapableHandleScope handle_scope(env->isolate());
36
6594
  CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
37
3297
  Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
38
3297
  CHECK_EQ(constructor.IsEmpty(), false);
39
6594
  Local<Value> ptr = External::New(env->isolate(), parent);
40
  Local<Object> instance =
41
6594
      constructor->NewInstance(env->context(), 1, &ptr).ToLocalChecked();
42
6594
  return handle_scope.Escape(instance);
43
}
44
45
46
1576
void TCPWrap::Initialize(Local<Object> target,
47
                         Local<Value> unused,
48
                         Local<Context> context) {
49
1576
  Environment* env = Environment::GetCurrent(context);
50
51
3152
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
52
1576
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"));
53
3152
  t->InstanceTemplate()->SetInternalFieldCount(1);
54
55
  // Init properties
56
9456
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "reading"),
57
1576
                             Boolean::New(env->isolate(), false));
58
9456
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "owner"),
59
1576
                             Null(env->isolate()));
60
9456
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "onread"),
61
1576
                             Null(env->isolate()));
62
9456
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(),
63
                                                 "onconnection"),
64
1576
                             Null(env->isolate()));
65
66
67
1576
  env->SetProtoMethod(t, "close", HandleWrap::Close);
68
69
1576
  env->SetProtoMethod(t, "ref", HandleWrap::Ref);
70
1576
  env->SetProtoMethod(t, "unref", HandleWrap::Unref);
71
1576
  env->SetProtoMethod(t, "hasRef", HandleWrap::HasRef);
72
73
1576
  StreamWrap::AddMethods(env, t, StreamBase::kFlagHasWritev);
74
75
1576
  env->SetProtoMethod(t, "open", Open);
76
1576
  env->SetProtoMethod(t, "bind", Bind);
77
1576
  env->SetProtoMethod(t, "listen", Listen);
78
1576
  env->SetProtoMethod(t, "connect", Connect);
79
1576
  env->SetProtoMethod(t, "bind6", Bind6);
80
1576
  env->SetProtoMethod(t, "connect6", Connect6);
81
  env->SetProtoMethod(t, "getsockname",
82
1576
                      GetSockOrPeerName<TCPWrap, uv_tcp_getsockname>);
83
  env->SetProtoMethod(t, "getpeername",
84
1576
                      GetSockOrPeerName<TCPWrap, uv_tcp_getpeername>);
85
1576
  env->SetProtoMethod(t, "setNoDelay", SetNoDelay);
86
1576
  env->SetProtoMethod(t, "setKeepAlive", SetKeepAlive);
87
88
#ifdef _WIN32
89
  env->SetProtoMethod(t, "setSimultaneousAccepts", SetSimultaneousAccepts);
90
#endif
91
92
4728
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"), t->GetFunction());
93
1576
  env->set_tcp_constructor_template(t);
94
95
  // Create FunctionTemplate for TCPConnectWrap.
96
2063
  auto constructor = [](const FunctionCallbackInfo<Value>& args) {
97
2063
    CHECK(args.IsConstructCall());
98
4126
  };
99
3152
  auto cwt = FunctionTemplate::New(env->isolate(), constructor);
100
3152
  cwt->InstanceTemplate()->SetInternalFieldCount(1);
101
1576
  cwt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"));
102
6304
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"),
103
1576
              cwt->GetFunction());
104
1576
}
105
106
107
5907
void TCPWrap::New(const FunctionCallbackInfo<Value>& args) {
108
  // This constructor should not be exposed to public javascript.
109
  // Therefore we assert that we are not trying to call this as a
110
  // normal function.
111
5907
  CHECK(args.IsConstructCall());
112
5907
  Environment* env = Environment::GetCurrent(args);
113
  TCPWrap* wrap;
114
5907
  if (args.Length() == 0) {
115
2610
    wrap = new TCPWrap(env, args.This(), nullptr);
116
3297
  } else if (args[0]->IsExternal()) {
117
6594
    void* ptr = args[0].As<External>()->Value();
118
3297
    wrap = new TCPWrap(env, args.This(), static_cast<AsyncWrap*>(ptr));
119
  } else {
120
    UNREACHABLE();
121
  }
122
5907
  CHECK(wrap);
123
5907
}
124
125
126
5907
TCPWrap::TCPWrap(Environment* env, Local<Object> object, AsyncWrap* parent)
127
    : ConnectionWrap(env,
128
                     object,
129
                     AsyncWrap::PROVIDER_TCPWRAP,
130
5907
                     parent) {
131
11814
  int r = uv_tcp_init(env->event_loop(), &handle_);
132
5907
  CHECK_EQ(r, 0);  // How do we proxy this error up to javascript?
133
                   // Suggestion: uv_tcp_init() returns void.
134
5907
  UpdateWriteQueueSize();
135
5907
}
136
137
138
23216
TCPWrap::~TCPWrap() {
139
11608
  CHECK(persistent().IsEmpty());
140
11608
}
141
142
143
8
void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) {
144
  TCPWrap* wrap;
145
8
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
146
                          args.Holder(),
147
                          args.GetReturnValue().Set(UV_EBADF));
148
8
  int enable = static_cast<int>(args[0]->BooleanValue());
149
8
  int err = uv_tcp_nodelay(&wrap->handle_, enable);
150
16
  args.GetReturnValue().Set(err);
151
}
152
153
154
34
void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
155
  TCPWrap* wrap;
156
34
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
157
                          args.Holder(),
158
                          args.GetReturnValue().Set(UV_EBADF));
159
34
  int enable = args[0]->Int32Value();
160
34
  unsigned int delay = args[1]->Uint32Value();
161
34
  int err = uv_tcp_keepalive(&wrap->handle_, enable, delay);
162
68
  args.GetReturnValue().Set(err);
163
}
164
165
166
#ifdef _WIN32
167
void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) {
168
  TCPWrap* wrap;
169
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
170
                          args.Holder(),
171
                          args.GetReturnValue().Set(UV_EBADF));
172
  bool enable = args[0]->BooleanValue();
173
  int err = uv_tcp_simultaneous_accepts(&wrap->handle_, enable);
174
  args.GetReturnValue().Set(err);
175
}
176
#endif
177
178
179
void TCPWrap::Open(const FunctionCallbackInfo<Value>& args) {
180
  TCPWrap* wrap;
181
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
182
                          args.Holder(),
183
                          args.GetReturnValue().Set(UV_EBADF));
184
  int fd = static_cast<int>(args[0]->IntegerValue());
185
  uv_tcp_open(&wrap->handle_, fd);
186
}
187
188
189
122
void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
190
  TCPWrap* wrap;
191
122
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
192
                          args.Holder(),
193
                          args.GetReturnValue().Set(UV_EBADF));
194
366
  node::Utf8Value ip_address(args.GetIsolate(), args[0]);
195
122
  int port = args[1]->Int32Value();
196
  sockaddr_in addr;
197
122
  int err = uv_ip4_addr(*ip_address, port, &addr);
198
122
  if (err == 0) {
199
122
    err = uv_tcp_bind(&wrap->handle_,
200
                      reinterpret_cast<const sockaddr*>(&addr),
201
122
                      0);
202
  }
203
244
  args.GetReturnValue().Set(err);
204
}
205
206
207
401
void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
208
  TCPWrap* wrap;
209
401
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
210
                          args.Holder(),
211
                          args.GetReturnValue().Set(UV_EBADF));
212
1203
  node::Utf8Value ip6_address(args.GetIsolate(), args[0]);
213
401
  int port = args[1]->Int32Value();
214
  sockaddr_in6 addr;
215
401
  int err = uv_ip6_addr(*ip6_address, port, &addr);
216
401
  if (err == 0) {
217
401
    err = uv_tcp_bind(&wrap->handle_,
218
                      reinterpret_cast<const sockaddr*>(&addr),
219
401
                      0);
220
  }
221
802
  args.GetReturnValue().Set(err);
222
}
223
224
225
508
void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
226
  TCPWrap* wrap;
227
508
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
228
                          args.Holder(),
229
                          args.GetReturnValue().Set(UV_EBADF));
230
508
  int backlog = args[0]->Int32Value();
231
508
  int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
232
                      backlog,
233
508
                      OnConnection);
234
1016
  args.GetReturnValue().Set(err);
235
}
236
237
238
2063
void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
239
2063
  ConnectWrap* req_wrap = static_cast<ConnectWrap*>(req->data);
240
2063
  TCPWrap* wrap = static_cast<TCPWrap*>(req->handle->data);
241
2063
  CHECK_EQ(req_wrap->env(), wrap->env());
242
2063
  Environment* env = wrap->env();
243
244
4126
  HandleScope handle_scope(env->isolate());
245
6189
  Context::Scope context_scope(env->context());
246
247
  // The wrap and request objects should still be there.
248
4126
  CHECK_EQ(req_wrap->persistent().IsEmpty(), false);
249
4126
  CHECK_EQ(wrap->persistent().IsEmpty(), false);
250
251
4126
  Local<Object> req_wrap_obj = req_wrap->object();
252
  Local<Value> argv[5] = {
253
    Integer::New(env->isolate(), status),
254
    wrap->object(),
255
    req_wrap_obj,
256
    v8::True(env->isolate()),
257
    v8::True(env->isolate())
258
18567
  };
259
260
4126
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
261
262
2063
  delete req_wrap;
263
2063
}
264
265
266
2054
void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
267
2054
  Environment* env = Environment::GetCurrent(args);
268
269
  TCPWrap* wrap;
270
2054
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
271
                          args.Holder(),
272
                          args.GetReturnValue().Set(UV_EBADF));
273
274
2054
  CHECK(args[0]->IsObject());
275
4108
  CHECK(args[1]->IsString());
276
2054
  CHECK(args[2]->IsUint32());
277
278
4108
  Local<Object> req_wrap_obj = args[0].As<Object>();
279
4108
  node::Utf8Value ip_address(env->isolate(), args[1]);
280
2054
  int port = args[2]->Uint32Value();
281
282
  sockaddr_in addr;
283
2054
  int err = uv_ip4_addr(*ip_address, port, &addr);
284
285
2054
  if (err == 0) {
286
    ConnectWrap* req_wrap =
287
2054
        new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
288
2054
    err = uv_tcp_connect(&req_wrap->req_,
289
                         &wrap->handle_,
290
                         reinterpret_cast<const sockaddr*>(&addr),
291
2054
                         AfterConnect);
292
4108
    req_wrap->Dispatched();
293
2054
    if (err)
294
      delete req_wrap;
295
  }
296
297
4108
  args.GetReturnValue().Set(err);
298
}
299
300
301
9
void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
302
9
  Environment* env = Environment::GetCurrent(args);
303
304
  TCPWrap* wrap;
305
9
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
306
                          args.Holder(),
307
                          args.GetReturnValue().Set(UV_EBADF));
308
309
9
  CHECK(args[0]->IsObject());
310
18
  CHECK(args[1]->IsString());
311
9
  CHECK(args[2]->IsUint32());
312
313
18
  Local<Object> req_wrap_obj = args[0].As<Object>();
314
18
  node::Utf8Value ip_address(env->isolate(), args[1]);
315
9
  int port = args[2]->Int32Value();
316
317
  sockaddr_in6 addr;
318
9
  int err = uv_ip6_addr(*ip_address, port, &addr);
319
320
9
  if (err == 0) {
321
    ConnectWrap* req_wrap =
322
9
        new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
323
9
    err = uv_tcp_connect(&req_wrap->req_,
324
                         &wrap->handle_,
325
                         reinterpret_cast<const sockaddr*>(&addr),
326
9
                         AfterConnect);
327
18
    req_wrap->Dispatched();
328
9
    if (err)
329
      delete req_wrap;
330
  }
331
332
18
  args.GetReturnValue().Set(err);
333
}
334
335
336
// also used by udp_wrap.cc
337
2313
Local<Object> AddressToJS(Environment* env,
338
                          const sockaddr* addr,
339
                          Local<Object> info) {
340
4626
  EscapableHandleScope scope(env->isolate());
341
  char ip[INET6_ADDRSTRLEN];
342
  const sockaddr_in *a4;
343
  const sockaddr_in6 *a6;
344
  int port;
345
346
2313
  if (info.IsEmpty())
347
564
    info = Object::New(env->isolate());
348
349
2313
  switch (addr->sa_family) {
350
  case AF_INET6:
351
1061
    a6 = reinterpret_cast<const sockaddr_in6*>(addr);
352
1061
    uv_inet_ntop(AF_INET6, &a6->sin6_addr, ip, sizeof ip);
353
1061
    port = ntohs(a6->sin6_port);
354
4244
    info->Set(env->address_string(), OneByteString(env->isolate(), ip));
355
4244
    info->Set(env->family_string(), env->ipv6_string());
356
4244
    info->Set(env->port_string(), Integer::New(env->isolate(), port));
357
1061
    break;
358
359
  case AF_INET:
360
1252
    a4 = reinterpret_cast<const sockaddr_in*>(addr);
361
1252
    uv_inet_ntop(AF_INET, &a4->sin_addr, ip, sizeof ip);
362
1252
    port = ntohs(a4->sin_port);
363
5008
    info->Set(env->address_string(), OneByteString(env->isolate(), ip));
364
5008
    info->Set(env->family_string(), env->ipv4_string());
365
5008
    info->Set(env->port_string(), Integer::New(env->isolate(), port));
366
1252
    break;
367
368
  default:
369
    info->Set(env->address_string(), String::Empty(env->isolate()));
370
  }
371
372
4626
  return scope.Escape(info);
373
}
374
375
376
}  // namespace node
377
378
1632
NODE_MODULE_CONTEXT_AWARE_BUILTIN(tcp_wrap, node::TCPWrap::Initialize)