From bb05aa320617ec3dc130c89d5b8eb1db362270e8 Mon Sep 17 00:00:00 2001
From: Daniel Bevenius <daniel.bevenius@gmail.com>
Date: Fri, 19 Oct 2018 11:27:45 +0200
Subject: [PATCH] src: reduce duplication in tcp_wrap Connect

This commit extracts identical code from Connect and Connect6 into a
separate function to avoid some code duplication.

PR-URL: https://github.com/nodejs/node/pull/23753
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matheus Marchini <mat@mmarchini.me>
---
 src/tcp_wrap.cc | 54 ++++++++++++++++++-------------------------------
 src/tcp_wrap.h  |  3 +++
 2 files changed, 23 insertions(+), 34 deletions(-)

diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc
index a07ba2d61231f4..f653297fc0ac8b 100644
--- a/src/tcp_wrap.cc
+++ b/src/tcp_wrap.cc
@@ -276,58 +276,44 @@ void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
 
 
 void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
-  Environment* env = Environment::GetCurrent(args);
-
-  TCPWrap* wrap;
-  ASSIGN_OR_RETURN_UNWRAP(&wrap,
-                          args.Holder(),
-                          args.GetReturnValue().Set(UV_EBADF));
-
-  CHECK(args[0]->IsObject());
-  CHECK(args[1]->IsString());
   CHECK(args[2]->IsUint32());
-
-  Local<Object> req_wrap_obj = args[0].As<Object>();
-  node::Utf8Value ip_address(env->isolate(), args[1]);
   int port = args[2].As<Uint32>()->Value();
+  Connect<sockaddr_in>(args,
+                       [port](const char* ip_address, sockaddr_in* addr) {
+      return uv_ip4_addr(ip_address, port, addr);
+  });
+}
 
-  sockaddr_in addr;
-  int err = uv_ip4_addr(*ip_address, port, &addr);
-
-  if (err == 0) {
-    AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
-    ConnectWrap* req_wrap =
-        new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
-    err = req_wrap->Dispatch(uv_tcp_connect,
-                             &wrap->handle_,
-                             reinterpret_cast<const sockaddr*>(&addr),
-                             AfterConnect);
-    if (err)
-      delete req_wrap;
-  }
 
-  args.GetReturnValue().Set(err);
+void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
+  Environment* env = Environment::GetCurrent(args);
+  CHECK(args[2]->IsUint32());
+  int port;
+  if (!args[2]->Int32Value(env->context()).To(&port)) return;
+  Connect<sockaddr_in6>(args,
+                        [port](const char* ip_address, sockaddr_in6* addr) {
+      return uv_ip6_addr(ip_address, port, addr);
+  });
 }
 
+template <typename T>
+void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args,
+    std::function<int(const char* ip_address, T* addr)> uv_ip_addr) {
+  Environment* env = Environment::GetCurrent(args);
 
-void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
   TCPWrap* wrap;
   ASSIGN_OR_RETURN_UNWRAP(&wrap,
                           args.Holder(),
                           args.GetReturnValue().Set(UV_EBADF));
-  Environment* env = wrap->env();
 
   CHECK(args[0]->IsObject());
   CHECK(args[1]->IsString());
-  CHECK(args[2]->IsUint32());
 
   Local<Object> req_wrap_obj = args[0].As<Object>();
   node::Utf8Value ip_address(env->isolate(), args[1]);
-  int port;
-  if (!args[2]->Int32Value(env->context()).To(&port)) return;
 
-  sockaddr_in6 addr;
-  int err = uv_ip6_addr(*ip_address, port, &addr);
+  T addr;
+  int err = uv_ip_addr(*ip_address, &addr);
 
   if (err == 0) {
     AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
diff --git a/src/tcp_wrap.h b/src/tcp_wrap.h
index 90c81bcae6fd6f..3cbeae6d64a949 100644
--- a/src/tcp_wrap.h
+++ b/src/tcp_wrap.h
@@ -75,6 +75,9 @@ class TCPWrap : public ConnectionWrap<TCPWrap, uv_tcp_t> {
   static void Listen(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void Connect6(const v8::FunctionCallbackInfo<v8::Value>& args);
+  template <typename T>
+  static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args,
+      std::function<int(const char* ip_address, T* addr)> uv_ip_addr);
   static void Open(const v8::FunctionCallbackInfo<v8::Value>& args);
 
 #ifdef _WIN32