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