GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/tcp_wrap.cc Lines: 156 164 95.1 %
Date: 2016-12-16 Branches: 35 71 49.3 %

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
3144
Local<Object> TCPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
35
6288
  EscapableHandleScope handle_scope(env->isolate());
36
6288
  CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
37
3144
  Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
38
3144
  CHECK_EQ(constructor.IsEmpty(), false);
39
6288
  Local<Value> ptr = External::New(env->isolate(), parent);
40
  Local<Object> instance =
41
6288
      constructor->NewInstance(env->context(), 1, &ptr).ToLocalChecked();
42
6288
  return handle_scope.Escape(instance);
43
}
44
45
46
1671
void TCPWrap::Initialize(Local<Object> target,
47
                         Local<Value> unused,
48
                         Local<Context> context) {
49
1671
  Environment* env = Environment::GetCurrent(context);
50
51
3342
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
52
1671
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"));
53
3342
  t->InstanceTemplate()->SetInternalFieldCount(1);
54
55
  // Init properties
56
10026
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "reading"),
57
1671
                             Boolean::New(env->isolate(), false));
58
10026
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "owner"),
59
1671
                             Null(env->isolate()));
60
10026
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "onread"),
61
1671
                             Null(env->isolate()));
62
10026
  t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(),
63
                                                 "onconnection"),
64
1671
                             Null(env->isolate()));
65
66
67
1671
  env->SetProtoMethod(t, "close", HandleWrap::Close);
68
69
1671
  env->SetProtoMethod(t, "ref", HandleWrap::Ref);
70
1671
  env->SetProtoMethod(t, "unref", HandleWrap::Unref);
71
1671
  env->SetProtoMethod(t, "hasRef", HandleWrap::HasRef);
72
73
1671
  StreamWrap::AddMethods(env, t, StreamBase::kFlagHasWritev);
74
75
1671
  env->SetProtoMethod(t, "open", Open);
76
1671
  env->SetProtoMethod(t, "bind", Bind);
77
1671
  env->SetProtoMethod(t, "listen", Listen);
78
1671
  env->SetProtoMethod(t, "connect", Connect);
79
1671
  env->SetProtoMethod(t, "bind6", Bind6);
80
1671
  env->SetProtoMethod(t, "connect6", Connect6);
81
  env->SetProtoMethod(t, "getsockname",
82
1671
                      GetSockOrPeerName<TCPWrap, uv_tcp_getsockname>);
83
  env->SetProtoMethod(t, "getpeername",
84
1671
                      GetSockOrPeerName<TCPWrap, uv_tcp_getpeername>);
85
1671
  env->SetProtoMethod(t, "setNoDelay", SetNoDelay);
86
1671
  env->SetProtoMethod(t, "setKeepAlive", SetKeepAlive);
87
88
#ifdef _WIN32
89
  env->SetProtoMethod(t, "setSimultaneousAccepts", SetSimultaneousAccepts);
90
#endif
91
92
5013
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"), t->GetFunction());
93
1671
  env->set_tcp_constructor_template(t);
94
95
  // Create FunctionTemplate for TCPConnectWrap.
96
3830
  auto constructor = [](const FunctionCallbackInfo<Value>& args) {
97
1915
    CHECK(args.IsConstructCall());
98
3830
  };
99
3342
  auto cwt = FunctionTemplate::New(env->isolate(), constructor);
100
3342
  cwt->InstanceTemplate()->SetInternalFieldCount(1);
101
1671
  cwt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"));
102
6684
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"),
103
1671
              cwt->GetFunction());
104
1671
}
105
106
107
5625
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
5625
  CHECK(args.IsConstructCall());
112
5625
  Environment* env = Environment::GetCurrent(args);
113
  TCPWrap* wrap;
114
5625
  if (args.Length() == 0) {
115
2481
    wrap = new TCPWrap(env, args.This(), nullptr);
116
3144
  } else if (args[0]->IsExternal()) {
117
6288
    void* ptr = args[0].As<External>()->Value();
118
3144
    wrap = new TCPWrap(env, args.This(), static_cast<AsyncWrap*>(ptr));
119
  } else {
120
    UNREACHABLE();
121
  }
122
5625
  CHECK(wrap);
123
5625
}
124
125
126
5625
TCPWrap::TCPWrap(Environment* env, Local<Object> object, AsyncWrap* parent)
127
    : ConnectionWrap(env,
128
                     object,
129
                     AsyncWrap::PROVIDER_TCPWRAP,
130
5625
                     parent) {
131
11250
  int r = uv_tcp_init(env->event_loop(), &handle_);
132
5625
  CHECK_EQ(r, 0);  // How do we proxy this error up to javascript?
133
                   // Suggestion: uv_tcp_init() returns void.
134
5625
  UpdateWriteQueueSize();
135
5625
}
136
137
138
22076
TCPWrap::~TCPWrap() {
139
11038
  CHECK(persistent().IsEmpty());
140
11038
}
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
36
void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
155
  TCPWrap* wrap;
156
36
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
157
                          args.Holder(),
158
                          args.GetReturnValue().Set(UV_EBADF));
159
36
  int enable = args[0]->Int32Value();
160
36
  unsigned int delay = args[1]->Uint32Value();
161
36
  int err = uv_tcp_keepalive(&wrap->handle_, enable, delay);
162
72
  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
124
void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
190
  TCPWrap* wrap;
191
124
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
192
                          args.Holder(),
193
                          args.GetReturnValue().Set(UV_EBADF));
194
372
  node::Utf8Value ip_address(args.GetIsolate(), args[0]);
195
124
  int port = args[1]->Int32Value();
196
  sockaddr_in addr;
197
124
  int err = uv_ip4_addr(*ip_address, port, &addr);
198
124
  if (err == 0) {
199
124
    err = uv_tcp_bind(&wrap->handle_,
200
                      reinterpret_cast<const sockaddr*>(&addr),
201
124
                      0);
202
  }
203
248
  args.GetReturnValue().Set(err);
204
}
205
206
207
417
void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
208
  TCPWrap* wrap;
209
417
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
210
                          args.Holder(),
211
                          args.GetReturnValue().Set(UV_EBADF));
212
1251
  node::Utf8Value ip6_address(args.GetIsolate(), args[0]);
213
417
  int port = args[1]->Int32Value();
214
  sockaddr_in6 addr;
215
417
  int err = uv_ip6_addr(*ip6_address, port, &addr);
216
417
  if (err == 0) {
217
417
    err = uv_tcp_bind(&wrap->handle_,
218
                      reinterpret_cast<const sockaddr*>(&addr),
219
417
                      0);
220
  }
221
834
  args.GetReturnValue().Set(err);
222
}
223
224
225
525
void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
226
  TCPWrap* wrap;
227
525
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
228
                          args.Holder(),
229
                          args.GetReturnValue().Set(UV_EBADF));
230
525
  int backlog = args[0]->Int32Value();
231
525
  int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
232
                      backlog,
233
525
                      OnConnection);
234
1050
  args.GetReturnValue().Set(err);
235
}
236
237
238
1904
void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
239
1904
  Environment* env = Environment::GetCurrent(args);
240
241
  TCPWrap* wrap;
242
1904
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
243
                          args.Holder(),
244
                          args.GetReturnValue().Set(UV_EBADF));
245
246
1904
  CHECK(args[0]->IsObject());
247
3808
  CHECK(args[1]->IsString());
248
1904
  CHECK(args[2]->IsUint32());
249
250
3808
  Local<Object> req_wrap_obj = args[0].As<Object>();
251
3808
  node::Utf8Value ip_address(env->isolate(), args[1]);
252
1904
  int port = args[2]->Uint32Value();
253
254
  sockaddr_in addr;
255
1904
  int err = uv_ip4_addr(*ip_address, port, &addr);
256
257
1904
  if (err == 0) {
258
    ConnectWrap* req_wrap =
259
1904
        new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
260
3808
    err = uv_tcp_connect(req_wrap->req(),
261
                         &wrap->handle_,
262
                         reinterpret_cast<const sockaddr*>(&addr),
263
1904
                         AfterConnect);
264
3808
    req_wrap->Dispatched();
265
1904
    if (err)
266
      delete req_wrap;
267
  }
268
269
3808
  args.GetReturnValue().Set(err);
270
}
271
272
273
11
void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
274
11
  Environment* env = Environment::GetCurrent(args);
275
276
  TCPWrap* wrap;
277
11
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
278
                          args.Holder(),
279
                          args.GetReturnValue().Set(UV_EBADF));
280
281
11
  CHECK(args[0]->IsObject());
282
22
  CHECK(args[1]->IsString());
283
11
  CHECK(args[2]->IsUint32());
284
285
22
  Local<Object> req_wrap_obj = args[0].As<Object>();
286
22
  node::Utf8Value ip_address(env->isolate(), args[1]);
287
11
  int port = args[2]->Int32Value();
288
289
  sockaddr_in6 addr;
290
11
  int err = uv_ip6_addr(*ip_address, port, &addr);
291
292
11
  if (err == 0) {
293
    ConnectWrap* req_wrap =
294
11
        new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
295
22
    err = uv_tcp_connect(req_wrap->req(),
296
                         &wrap->handle_,
297
                         reinterpret_cast<const sockaddr*>(&addr),
298
11
                         AfterConnect);
299
22
    req_wrap->Dispatched();
300
11
    if (err)
301
      delete req_wrap;
302
  }
303
304
22
  args.GetReturnValue().Set(err);
305
}
306
307
308
// also used by udp_wrap.cc
309
1537
Local<Object> AddressToJS(Environment* env,
310
                          const sockaddr* addr,
311
                          Local<Object> info) {
312
3074
  EscapableHandleScope scope(env->isolate());
313
  char ip[INET6_ADDRSTRLEN];
314
  const sockaddr_in *a4;
315
  const sockaddr_in6 *a6;
316
  int port;
317
318
1537
  if (info.IsEmpty())
319
391
    info = Object::New(env->isolate());
320
321
1537
  switch (addr->sa_family) {
322
  case AF_INET6:
323
907
    a6 = reinterpret_cast<const sockaddr_in6*>(addr);
324
907
    uv_inet_ntop(AF_INET6, &a6->sin6_addr, ip, sizeof ip);
325
907
    port = ntohs(a6->sin6_port);
326
3628
    info->Set(env->address_string(), OneByteString(env->isolate(), ip));
327
3628
    info->Set(env->family_string(), env->ipv6_string());
328
3628
    info->Set(env->port_string(), Integer::New(env->isolate(), port));
329
907
    break;
330
331
  case AF_INET:
332
630
    a4 = reinterpret_cast<const sockaddr_in*>(addr);
333
630
    uv_inet_ntop(AF_INET, &a4->sin_addr, ip, sizeof ip);
334
630
    port = ntohs(a4->sin_port);
335
2520
    info->Set(env->address_string(), OneByteString(env->isolate(), ip));
336
2520
    info->Set(env->family_string(), env->ipv4_string());
337
2520
    info->Set(env->port_string(), Integer::New(env->isolate(), port));
338
630
    break;
339
340
  default:
341
    info->Set(env->address_string(), String::Empty(env->isolate()));
342
  }
343
344
3074
  return scope.Escape(info);
345
}
346
347
348
}  // namespace node
349
350
1729
NODE_MODULE_CONTEXT_AWARE_BUILTIN(tcp_wrap, node::TCPWrap::Initialize)