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