Advertisement
Guest User

Tcp Wrap NodeJS

a guest
Aug 20th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.94 KB | None | 0 0
  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-inl.h"
  26. #include "handle_wrap.h"
  27. #include "node_buffer.h"
  28. #include "node_internals.h"
  29. #include "connect_wrap.h"
  30. #include "stream_base-inl.h"
  31. #include "stream_wrap.h"
  32. #include "util-inl.h"
  33.  
  34. #include <cstdlib>
  35.  
  36.  
  37. namespace node {
  38.  
  39. using v8::Boolean;
  40. using v8::Context;
  41. using v8::EscapableHandleScope;
  42. using v8::Function;
  43. using v8::FunctionCallbackInfo;
  44. using v8::FunctionTemplate;
  45. using v8::HandleScope;
  46. using v8::Int32;
  47. using v8::Integer;
  48. using v8::Local;
  49. using v8::MaybeLocal;
  50. using v8::Object;
  51. using v8::String;
  52. using v8::Uint32;
  53. using v8::Value;
  54.  
  55. MaybeLocal<Object> TCPWrap::Instantiate(Environment* env,
  56. AsyncWrap* parent,
  57. TCPWrap::SocketType type) {
  58. EscapableHandleScope handle_scope(env->isolate());
  59. AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent);
  60. CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
  61. Local<Function> constructor = env->tcp_constructor_template()
  62. ->GetFunction(env->context())
  63. .ToLocalChecked();
  64. CHECK_EQ(constructor.IsEmpty(), false);
  65. Local<Value> type_value = Int32::New(env->isolate(), type);
  66. return handle_scope.EscapeMaybe(
  67. constructor->NewInstance(env->context(), 1, &type_value));
  68. }
  69.  
  70.  
  71. void TCPWrap::Initialize(Local<Object> target,
  72. Local<Value> unused,
  73. Local<Context> context,
  74. void* priv) {
  75. Environment* env = Environment::GetCurrent(context);
  76.  
  77. Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
  78. Local<String> tcpString = FIXED_ONE_BYTE_STRING(env->isolate(), "TCP");
  79. t->SetClassName(tcpString);
  80. t->InstanceTemplate()
  81. ->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount);
  82.  
  83. // Init properties
  84. t->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "reading"),
  85. Boolean::New(env->isolate(), false));
  86. t->InstanceTemplate()->Set(env->owner_symbol(), Null(env->isolate()));
  87. t->InstanceTemplate()->Set(env->onconnection_string(), Null(env->isolate()));
  88.  
  89. t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env));
  90.  
  91. env->SetProtoMethod(t, "open", Open);
  92. env->SetProtoMethod(t, "bind", Bind);
  93. env->SetProtoMethod(t, "listen", Listen);
  94. env->SetProtoMethod(t, "connect", Connect);
  95. env->SetProtoMethod(t, "bind6", Bind6);
  96. env->SetProtoMethod(t, "connect6", Connect6);
  97. env->SetProtoMethod(t, "getsockname",
  98. GetSockOrPeerName<TCPWrap, uv_tcp_getsockname>);
  99. env->SetProtoMethod(t, "getpeername",
  100. GetSockOrPeerName<TCPWrap, uv_tcp_getpeername>);
  101. env->SetProtoMethod(t, "setNoDelay", SetNoDelay);
  102. env->SetProtoMethod(t, "setKeepAlive", SetKeepAlive);
  103.  
  104. #ifdef _WIN32
  105. env->SetProtoMethod(t, "setSimultaneousAccepts", SetSimultaneousAccepts);
  106. #endif
  107.  
  108. target->Set(env->context(),
  109. tcpString,
  110. t->GetFunction(env->context()).ToLocalChecked()).Check();
  111. env->set_tcp_constructor_template(t);
  112.  
  113. // Create FunctionTemplate for TCPConnectWrap.
  114. Local<FunctionTemplate> cwt =
  115. BaseObject::MakeLazilyInitializedJSTemplate(env);
  116. cwt->Inherit(AsyncWrap::GetConstructorTemplate(env));
  117. Local<String> wrapString =
  118. FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap");
  119. cwt->SetClassName(wrapString);
  120. target->Set(env->context(),
  121. wrapString,
  122. cwt->GetFunction(env->context()).ToLocalChecked()).Check();
  123.  
  124. // Define constants
  125. Local<Object> constants = Object::New(env->isolate());
  126. NODE_DEFINE_CONSTANT(constants, SOCKET);
  127. NODE_DEFINE_CONSTANT(constants, SERVER);
  128. NODE_DEFINE_CONSTANT(constants, UV_TCP_IPV6ONLY);
  129. target->Set(context,
  130. env->constants_string(),
  131. constants).Check();
  132. }
  133.  
  134.  
  135. void TCPWrap::New(const FunctionCallbackInfo<Value>& args) {
  136. // This constructor should not be exposed to public javascript.
  137. // Therefore we assert that we are not trying to call this as a
  138. // normal function.
  139. CHECK(args.IsConstructCall());
  140. CHECK(args[0]->IsInt32());
  141. Environment* env = Environment::GetCurrent(args);
  142.  
  143. int type_value = args[0].As<Int32>()->Value();
  144. TCPWrap::SocketType type = static_cast<TCPWrap::SocketType>(type_value);
  145.  
  146. ProviderType provider;
  147. switch (type) {
  148. case SOCKET:
  149. provider = PROVIDER_TCPWRAP;
  150. break;
  151. case SERVER:
  152. provider = PROVIDER_TCPSERVERWRAP;
  153. break;
  154. default:
  155. UNREACHABLE();
  156. }
  157.  
  158. new TCPWrap(env, args.This(), provider);
  159. }
  160.  
  161.  
  162. TCPWrap::TCPWrap(Environment* env, Local<Object> object, ProviderType provider)
  163. : ConnectionWrap(env, object, provider) {
  164. int r = uv_tcp_init(env->event_loop(), &handle_);
  165. CHECK_EQ(r, 0); // How do we proxy this error up to javascript?
  166. // Suggestion: uv_tcp_init() returns void.
  167. }
  168.  
  169.  
  170. void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) {
  171. TCPWrap* wrap;
  172. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  173. args.Holder(),
  174. args.GetReturnValue().Set(UV_EBADF));
  175. int enable = static_cast<int>(args[0]->IsTrue());
  176. int err = uv_tcp_nodelay(&wrap->handle_, enable);
  177. args.GetReturnValue().Set(err);
  178. }
  179.  
  180.  
  181. void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
  182. TCPWrap* wrap;
  183. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  184. args.Holder(),
  185. args.GetReturnValue().Set(UV_EBADF));
  186. Environment* env = wrap->env();
  187. int enable;
  188. if (!args[0]->Int32Value(env->context()).To(&enable)) return;
  189. unsigned int delay = args[1].As<Uint32>()->Value();
  190. int err = uv_tcp_keepalive(&wrap->handle_, enable, delay);
  191. args.GetReturnValue().Set(err);
  192. }
  193.  
  194.  
  195. #ifdef _WIN32
  196. void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) {
  197. TCPWrap* wrap;
  198. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  199. args.Holder(),
  200. args.GetReturnValue().Set(UV_EBADF));
  201. bool enable = args[0]->IsTrue();
  202. int err = uv_tcp_simultaneous_accepts(&wrap->handle_, enable);
  203. args.GetReturnValue().Set(err);
  204. }
  205. #endif
  206.  
  207.  
  208. void TCPWrap::Open(const FunctionCallbackInfo<Value>& args) {
  209. TCPWrap* wrap;
  210. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  211. args.Holder(),
  212. args.GetReturnValue().Set(UV_EBADF));
  213. int64_t val;
  214. if (!args[0]->IntegerValue(args.GetIsolate()->GetCurrentContext()).To(&val))
  215. return;
  216. int fd = static_cast<int>(val);
  217. int err = uv_tcp_open(&wrap->handle_, fd);
  218.  
  219. if (err == 0)
  220. wrap->set_fd(fd);
  221.  
  222. args.GetReturnValue().Set(err);
  223. }
  224.  
  225. template <typename T>
  226. void TCPWrap::Bind(
  227. const FunctionCallbackInfo<Value>& args,
  228. int family,
  229. std::function<int(const char* ip_address, int port, T* addr)> uv_ip_addr) {
  230. TCPWrap* wrap;
  231. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  232. args.Holder(),
  233. args.GetReturnValue().Set(UV_EBADF));
  234. Environment* env = wrap->env();
  235. node::Utf8Value ip_address(env->isolate(), args[0]);
  236. int port;
  237. unsigned int flags = 0;
  238. if (!args[1]->Int32Value(env->context()).To(&port)) return;
  239. if (family == AF_INET6 &&
  240. !args[2]->Uint32Value(env->context()).To(&flags)) {
  241. return;
  242. }
  243.  
  244. T addr;
  245. int err = uv_ip_addr(*ip_address, port, &addr);
  246.  
  247. if (err == 0) {
  248. err = uv_tcp_bind(&wrap->handle_,
  249. reinterpret_cast<const sockaddr*>(&addr),
  250. flags);
  251. }
  252. args.GetReturnValue().Set(err);
  253. }
  254.  
  255. void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
  256. Bind<sockaddr_in>(args, AF_INET, uv_ip4_addr);
  257. }
  258.  
  259.  
  260. void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
  261. Bind<sockaddr_in6>(args, AF_INET6, uv_ip6_addr);
  262. }
  263.  
  264.  
  265. void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
  266. TCPWrap* wrap;
  267. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  268. args.Holder(),
  269. args.GetReturnValue().Set(UV_EBADF));
  270. Environment* env = wrap->env();
  271. int backlog;
  272. if (!args[0]->Int32Value(env->context()).To(&backlog)) return;
  273. int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
  274. backlog,
  275. OnConnection);
  276. args.GetReturnValue().Set(err);
  277. }
  278.  
  279.  
  280. void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
  281. CHECK(args[2]->IsUint32());
  282. int port = args[2].As<Uint32>()->Value();
  283. Connect<sockaddr_in>(args,
  284. [port](const char* ip_address, sockaddr_in* addr) {
  285. return uv_ip4_addr(ip_address, port, addr);
  286. });
  287. }
  288.  
  289.  
  290. void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
  291. Environment* env = Environment::GetCurrent(args);
  292. CHECK(args[2]->IsUint32());
  293. int port;
  294. if (!args[2]->Int32Value(env->context()).To(&port)) return;
  295. Connect<sockaddr_in6>(args,
  296. [port](const char* ip_address, sockaddr_in6* addr) {
  297. return uv_ip6_addr(ip_address, port, addr);
  298. });
  299. }
  300.  
  301. template <typename T>
  302. void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args,
  303. std::function<int(const char* ip_address, T* addr)> uv_ip_addr) {
  304. Environment* env = Environment::GetCurrent(args);
  305.  
  306. TCPWrap* wrap;
  307. ASSIGN_OR_RETURN_UNWRAP(&wrap,
  308. args.Holder(),
  309. args.GetReturnValue().Set(UV_EBADF));
  310.  
  311. CHECK(args[0]->IsObject());
  312. CHECK(args[1]->IsString());
  313.  
  314. Local<Object> req_wrap_obj = args[0].As<Object>();
  315. node::Utf8Value ip_address(env->isolate(), args[1]);
  316.  
  317. T addr;
  318. int err = uv_ip_addr(*ip_address, &addr);
  319.  
  320. if (err == 0) {
  321. AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
  322. ConnectWrap* req_wrap =
  323. new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
  324. err = req_wrap->Dispatch(uv_tcp_connect,
  325. &wrap->handle_,
  326. reinterpret_cast<const sockaddr*>(&addr),
  327. AfterConnect);
  328. if (err)
  329. delete req_wrap;
  330. }
  331.  
  332. args.GetReturnValue().Set(err);
  333. }
  334.  
  335.  
  336. // also used by udp_wrap.cc
  337. Local<Object> AddressToJS(Environment* env,
  338. const sockaddr* addr,
  339. Local<Object> info) {
  340. EscapableHandleScope scope(env->isolate());
  341. char ip[INET6_ADDRSTRLEN];
  342. const sockaddr_in* a4;
  343. const sockaddr_in6* a6;
  344. int port;
  345.  
  346. if (info.IsEmpty())
  347. info = Object::New(env->isolate());
  348.  
  349. switch (addr->sa_family) {
  350. case AF_INET6:
  351. a6 = reinterpret_cast<const sockaddr_in6*>(addr);
  352. uv_inet_ntop(AF_INET6, &a6->sin6_addr, ip, sizeof ip);
  353. port = ntohs(a6->sin6_port);
  354. info->Set(env->context(),
  355. env->address_string(),
  356. OneByteString(env->isolate(), ip)).Check();
  357. info->Set(env->context(),
  358. env->family_string(),
  359. env->ipv6_string()).Check();
  360. info->Set(env->context(),
  361. env->port_string(),
  362. Integer::New(env->isolate(), port)).Check();
  363. break;
  364.  
  365. case AF_INET:
  366. a4 = reinterpret_cast<const sockaddr_in*>(addr);
  367. uv_inet_ntop(AF_INET, &a4->sin_addr, ip, sizeof ip);
  368. port = ntohs(a4->sin_port);
  369. info->Set(env->context(),
  370. env->address_string(),
  371. OneByteString(env->isolate(), ip)).Check();
  372. info->Set(env->context(),
  373. env->family_string(),
  374. env->ipv4_string()).Check();
  375. info->Set(env->context(),
  376. env->port_string(),
  377. Integer::New(env->isolate(), port)).Check();
  378. break;
  379.  
  380. default:
  381. info->Set(env->context(),
  382. env->address_string(),
  383. String::Empty(env->isolate())).Check();
  384. }
  385.  
  386. return scope.Escape(info);
  387. }
  388.  
  389.  
  390. } // namespace node
  391.  
  392. NODE_MODULE_CONTEXT_AWARE_INTERNAL(tcp_wrap, node::TCPWrap::Initialize)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement