GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/tcp_wrap.cc Lines: 193 203 95.1 %
Date: 2016-07-23 Branches: 44 89 49.4 %

Line Exec Source
1
#include "tcp_wrap.h"
2
3
#include "env.h"
4
#include "env-inl.h"
5
#include "handle_wrap.h"
6
#include "node_buffer.h"
7
#include "node_wrap.h"
8
#include "req-wrap.h"
9
#include "req-wrap-inl.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::Undefined;
32
using v8::Value;
33
34
35
2091
class TCPConnectWrap : public ReqWrap<uv_connect_t> {
36
 public:
37
  TCPConnectWrap(Environment* env, Local<Object> req_wrap_obj);
38
  size_t self_size() const override { return sizeof(*this); }
39
};
40
41
42
2091
TCPConnectWrap::TCPConnectWrap(Environment* env, Local<Object> req_wrap_obj)
43
2091
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP) {
44
2091
  Wrap(req_wrap_obj, this);
45
2091
}
46
47
48
2091
static void NewTCPConnectWrap(const FunctionCallbackInfo<Value>& args) {
49
2091
  CHECK(args.IsConstructCall());
50
2091
}
51
52
53
3219
Local<Object> TCPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
54
6438
  EscapableHandleScope handle_scope(env->isolate());
55
6438
  CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
56
3219
  Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
57
3219
  CHECK_EQ(constructor.IsEmpty(), false);
58
6438
  Local<Value> ptr = External::New(env->isolate(), parent);
59
  Local<Object> instance =
60
6438
      constructor->NewInstance(env->context(), 1, &ptr).ToLocalChecked();
61
6438
  return handle_scope.Escape(instance);
62
}
63
64
65
1512
void TCPWrap::Initialize(Local<Object> target,
66
                         Local<Value> unused,
67
                         Local<Context> context) {
68
1512
  Environment* env = Environment::GetCurrent(context);
69
70
3024
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
71
1512
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"));
72
3024
  t->InstanceTemplate()->SetInternalFieldCount(1);
73
74
  // Init properties
75
9072
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "reading"),
76
1512
                             Boolean::New(env->isolate(), false));
77
9072
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "owner"),
78
1512
                             Null(env->isolate()));
79
9072
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "onread"),
80
1512
                             Null(env->isolate()));
81
9072
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(),
82
                                                 "onconnection"),
83
1512
                             Null(env->isolate()));
84
85
86
1512
  env->SetProtoMethod(t, "close", HandleWrap::Close);
87
88
1512
  env->SetProtoMethod(t, "ref", HandleWrap::Ref);
89
1512
  env->SetProtoMethod(t, "unref", HandleWrap::Unref);
90
1512
  env->SetProtoMethod(t, "hasRef", HandleWrap::HasRef);
91
92
1512
  StreamWrap::AddMethods(env, t, StreamBase::kFlagHasWritev);
93
94
1512
  env->SetProtoMethod(t, "open", Open);
95
1512
  env->SetProtoMethod(t, "bind", Bind);
96
1512
  env->SetProtoMethod(t, "listen", Listen);
97
1512
  env->SetProtoMethod(t, "connect", Connect);
98
1512
  env->SetProtoMethod(t, "bind6", Bind6);
99
1512
  env->SetProtoMethod(t, "connect6", Connect6);
100
  env->SetProtoMethod(t, "getsockname",
101
1512
                      GetSockOrPeerName<TCPWrap, uv_tcp_getsockname>);
102
  env->SetProtoMethod(t, "getpeername",
103
1512
                      GetSockOrPeerName<TCPWrap, uv_tcp_getpeername>);
104
1512
  env->SetProtoMethod(t, "setNoDelay", SetNoDelay);
105
1512
  env->SetProtoMethod(t, "setKeepAlive", SetKeepAlive);
106
107
#ifdef _WIN32
108
  env->SetProtoMethod(t, "setSimultaneousAccepts", SetSimultaneousAccepts);
109
#endif
110
111
4536
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"), t->GetFunction());
112
1512
  env->set_tcp_constructor_template(t);
113
114
  // Create FunctionTemplate for TCPConnectWrap.
115
  Local<FunctionTemplate> cwt =
116
3024
      FunctionTemplate::New(env->isolate(), NewTCPConnectWrap);
117
3024
  cwt->InstanceTemplate()->SetInternalFieldCount(1);
118
1512
  cwt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"));
119
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"),
120
1512
              cwt->GetFunction());
121
1512
}
122
123
124
48
uv_tcp_t* TCPWrap::UVHandle() {
125
48
  return &handle_;
126
}
127
128
129
5856
void TCPWrap::New(const FunctionCallbackInfo<Value>& args) {
130
  // This constructor should not be exposed to public javascript.
131
  // Therefore we assert that we are not trying to call this as a
132
  // normal function.
133
5856
  CHECK(args.IsConstructCall());
134
5856
  Environment* env = Environment::GetCurrent(args);
135
  TCPWrap* wrap;
136
5856
  if (args.Length() == 0) {
137
2637
    wrap = new TCPWrap(env, args.This(), nullptr);
138
3219
  } else if (args[0]->IsExternal()) {
139
6438
    void* ptr = args[0].As<External>()->Value();
140
3219
    wrap = new TCPWrap(env, args.This(), static_cast<AsyncWrap*>(ptr));
141
  } else {
142
    UNREACHABLE();
143
  }
144
5856
  CHECK(wrap);
145
5856
}
146
147
148
5856
TCPWrap::TCPWrap(Environment* env, Local<Object> object, AsyncWrap* parent)
149
    : StreamWrap(env,
150
                 object,
151
                 reinterpret_cast<uv_stream_t*>(&handle_),
152
                 AsyncWrap::PROVIDER_TCPWRAP,
153
5856
                 parent) {
154
11712
  int r = uv_tcp_init(env->event_loop(), &handle_);
155
5856
  CHECK_EQ(r, 0);  // How do we proxy this error up to javascript?
156
                   // Suggestion: uv_tcp_init() returns void.
157
5856
  UpdateWriteQueueSize();
158
5856
}
159
160
161
23012
TCPWrap::~TCPWrap() {
162
11506
  CHECK(persistent().IsEmpty());
163
11506
}
164
165
166
8
void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) {
167
  TCPWrap* wrap;
168
8
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
169
                          args.Holder(),
170
                          args.GetReturnValue().Set(UV_EBADF));
171
8
  int enable = static_cast<int>(args[0]->BooleanValue());
172
8
  int err = uv_tcp_nodelay(&wrap->handle_, enable);
173
16
  args.GetReturnValue().Set(err);
174
}
175
176
177
34
void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
178
  TCPWrap* wrap;
179
34
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
180
                          args.Holder(),
181
                          args.GetReturnValue().Set(UV_EBADF));
182
34
  int enable = args[0]->Int32Value();
183
34
  unsigned int delay = args[1]->Uint32Value();
184
34
  int err = uv_tcp_keepalive(&wrap->handle_, enable, delay);
185
68
  args.GetReturnValue().Set(err);
186
}
187
188
189
#ifdef _WIN32
190
void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) {
191
  TCPWrap* wrap;
192
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
193
                          args.Holder(),
194
                          args.GetReturnValue().Set(UV_EBADF));
195
  bool enable = args[0]->BooleanValue();
196
  int err = uv_tcp_simultaneous_accepts(&wrap->handle_, enable);
197
  args.GetReturnValue().Set(err);
198
}
199
#endif
200
201
202
void TCPWrap::Open(const FunctionCallbackInfo<Value>& args) {
203
  TCPWrap* wrap;
204
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
205
                          args.Holder(),
206
                          args.GetReturnValue().Set(UV_EBADF));
207
  int fd = static_cast<int>(args[0]->IntegerValue());
208
  uv_tcp_open(&wrap->handle_, fd);
209
}
210
211
212
117
void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
213
  TCPWrap* wrap;
214
117
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
215
                          args.Holder(),
216
                          args.GetReturnValue().Set(UV_EBADF));
217
351
  node::Utf8Value ip_address(args.GetIsolate(), args[0]);
218
117
  int port = args[1]->Int32Value();
219
  sockaddr_in addr;
220
117
  int err = uv_ip4_addr(*ip_address, port, &addr);
221
117
  if (err == 0) {
222
117
    err = uv_tcp_bind(&wrap->handle_,
223
                      reinterpret_cast<const sockaddr*>(&addr),
224
117
                      0);
225
  }
226
234
  args.GetReturnValue().Set(err);
227
}
228
229
230
405
void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
231
  TCPWrap* wrap;
232
405
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
233
                          args.Holder(),
234
                          args.GetReturnValue().Set(UV_EBADF));
235
1215
  node::Utf8Value ip6_address(args.GetIsolate(), args[0]);
236
405
  int port = args[1]->Int32Value();
237
  sockaddr_in6 addr;
238
405
  int err = uv_ip6_addr(*ip6_address, port, &addr);
239
405
  if (err == 0) {
240
405
    err = uv_tcp_bind(&wrap->handle_,
241
                      reinterpret_cast<const sockaddr*>(&addr),
242
405
                      0);
243
  }
244
810
  args.GetReturnValue().Set(err);
245
}
246
247
248
507
void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
249
  TCPWrap* wrap;
250
507
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
251
                          args.Holder(),
252
                          args.GetReturnValue().Set(UV_EBADF));
253
507
  int backlog = args[0]->Int32Value();
254
507
  int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
255
                      backlog,
256
507
                      OnConnection);
257
1014
  args.GetReturnValue().Set(err);
258
}
259
260
261
3171
void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
262
3171
  TCPWrap* tcp_wrap = static_cast<TCPWrap*>(handle->data);
263
3171
  CHECK_EQ(&tcp_wrap->handle_, reinterpret_cast<uv_tcp_t*>(handle));
264
3171
  Environment* env = tcp_wrap->env();
265
266
6342
  HandleScope handle_scope(env->isolate());
267
9513
  Context::Scope context_scope(env->context());
268
269
  // We should not be getting this callback if someone as already called
270
  // uv_close() on the handle.
271
6342
  CHECK_EQ(tcp_wrap->persistent().IsEmpty(), false);
272
273
  Local<Value> argv[2] = {
274
    Integer::New(env->isolate(), status),
275
    Undefined(env->isolate())
276
12684
  };
277
278
3171
  if (status == 0) {
279
    // Instantiate the client javascript object and handle.
280
    Local<Object> client_obj =
281
3171
        Instantiate(env, static_cast<AsyncWrap*>(tcp_wrap));
282
283
    // Unwrap the client javascript object.
284
3171
    TCPWrap* wrap = Unwrap<TCPWrap>(client_obj);
285
3171
    CHECK_NE(wrap, nullptr);
286
3171
    uv_stream_t* client_handle = reinterpret_cast<uv_stream_t*>(&wrap->handle_);
287
3171
    if (uv_accept(handle, client_handle))
288
      return;
289
290
    // Successful accept. Call the onconnection callback in JavaScript land.
291
3171
    argv[1] = client_obj;
292
  }
293
294
6342
  tcp_wrap->MakeCallback(env->onconnection_string(), arraysize(argv), argv);
295
}
296
297
298
2091
void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
299
2091
  TCPConnectWrap* req_wrap = static_cast<TCPConnectWrap*>(req->data);
300
2091
  TCPWrap* wrap = static_cast<TCPWrap*>(req->handle->data);
301
2091
  CHECK_EQ(req_wrap->env(), wrap->env());
302
2091
  Environment* env = wrap->env();
303
304
4182
  HandleScope handle_scope(env->isolate());
305
6273
  Context::Scope context_scope(env->context());
306
307
  // The wrap and request objects should still be there.
308
4182
  CHECK_EQ(req_wrap->persistent().IsEmpty(), false);
309
4182
  CHECK_EQ(wrap->persistent().IsEmpty(), false);
310
311
4182
  Local<Object> req_wrap_obj = req_wrap->object();
312
  Local<Value> argv[5] = {
313
    Integer::New(env->isolate(), status),
314
    wrap->object(),
315
    req_wrap_obj,
316
    v8::True(env->isolate()),
317
    v8::True(env->isolate())
318
18819
  };
319
320
4182
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
321
322
2091
  delete req_wrap;
323
2091
}
324
325
326
2082
void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
327
2082
  Environment* env = Environment::GetCurrent(args);
328
329
  TCPWrap* wrap;
330
2082
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
331
                          args.Holder(),
332
                          args.GetReturnValue().Set(UV_EBADF));
333
334
2082
  CHECK(args[0]->IsObject());
335
4164
  CHECK(args[1]->IsString());
336
2082
  CHECK(args[2]->IsUint32());
337
338
4164
  Local<Object> req_wrap_obj = args[0].As<Object>();
339
4164
  node::Utf8Value ip_address(env->isolate(), args[1]);
340
2082
  int port = args[2]->Uint32Value();
341
342
  sockaddr_in addr;
343
2082
  int err = uv_ip4_addr(*ip_address, port, &addr);
344
345
2082
  if (err == 0) {
346
2082
    TCPConnectWrap* req_wrap = new TCPConnectWrap(env, req_wrap_obj);
347
2082
    err = uv_tcp_connect(&req_wrap->req_,
348
                         &wrap->handle_,
349
                         reinterpret_cast<const sockaddr*>(&addr),
350
2082
                         AfterConnect);
351
4164
    req_wrap->Dispatched();
352
2082
    if (err)
353
      delete req_wrap;
354
  }
355
356
4164
  args.GetReturnValue().Set(err);
357
}
358
359
360
9
void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
361
9
  Environment* env = Environment::GetCurrent(args);
362
363
  TCPWrap* wrap;
364
9
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
365
                          args.Holder(),
366
                          args.GetReturnValue().Set(UV_EBADF));
367
368
9
  CHECK(args[0]->IsObject());
369
18
  CHECK(args[1]->IsString());
370
9
  CHECK(args[2]->IsUint32());
371
372
18
  Local<Object> req_wrap_obj = args[0].As<Object>();
373
18
  node::Utf8Value ip_address(env->isolate(), args[1]);
374
9
  int port = args[2]->Int32Value();
375
376
  sockaddr_in6 addr;
377
9
  int err = uv_ip6_addr(*ip_address, port, &addr);
378
379
9
  if (err == 0) {
380
9
    TCPConnectWrap* req_wrap = new TCPConnectWrap(env, req_wrap_obj);
381
9
    err = uv_tcp_connect(&req_wrap->req_,
382
                         &wrap->handle_,
383
                         reinterpret_cast<const sockaddr*>(&addr),
384
9
                         AfterConnect);
385
18
    req_wrap->Dispatched();
386
9
    if (err)
387
      delete req_wrap;
388
  }
389
390
18
  args.GetReturnValue().Set(err);
391
}
392
393
394
// also used by udp_wrap.cc
395
2087
Local<Object> AddressToJS(Environment* env,
396
                          const sockaddr* addr,
397
                          Local<Object> info) {
398
4174
  EscapableHandleScope scope(env->isolate());
399
  char ip[INET6_ADDRSTRLEN];
400
  const sockaddr_in *a4;
401
  const sockaddr_in6 *a6;
402
  int port;
403
404
2087
  if (info.IsEmpty())
405
452
    info = Object::New(env->isolate());
406
407
2087
  switch (addr->sa_family) {
408
  case AF_INET6:
409
1064
    a6 = reinterpret_cast<const sockaddr_in6*>(addr);
410
1064
    uv_inet_ntop(AF_INET6, &a6->sin6_addr, ip, sizeof ip);
411
1064
    port = ntohs(a6->sin6_port);
412
4256
    info->Set(env->address_string(), OneByteString(env->isolate(), ip));
413
4256
    info->Set(env->family_string(), env->ipv6_string());
414
4256
    info->Set(env->port_string(), Integer::New(env->isolate(), port));
415
1064
    break;
416
417
  case AF_INET:
418
1023
    a4 = reinterpret_cast<const sockaddr_in*>(addr);
419
1023
    uv_inet_ntop(AF_INET, &a4->sin_addr, ip, sizeof ip);
420
1023
    port = ntohs(a4->sin_port);
421
4092
    info->Set(env->address_string(), OneByteString(env->isolate(), ip));
422
4092
    info->Set(env->family_string(), env->ipv4_string());
423
4092
    info->Set(env->port_string(), Integer::New(env->isolate(), port));
424
1023
    break;
425
426
  default:
427
    info->Set(env->address_string(), String::Empty(env->isolate()));
428
  }
429
430
4174
  return scope.Escape(info);
431
}
432
433
434
}  // namespace node
435
436
1569
NODE_MODULE_CONTEXT_AWARE_BUILTIN(tcp_wrap, node::TCPWrap::Initialize)