GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/tcp_wrap.cc Lines: 155 158 98.1 %
Date: 2017-06-14 Branches: 31 63 49.2 %

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