diff --git a/include/opendht/utils.h b/include/opendht/utils.h
index a762129600ecce5dc8f71e55f95eb113da6a5d7e..eb79078d58b89d019deb4cc8fb238ad148b48922 100644
--- a/include/opendht/utils.h
+++ b/include/opendht/utils.h
@@ -54,6 +54,12 @@ void erase_if(std::map<Key, Item>& map, const Condition& condition)
     }
 }
 
+/**
+ * Split "[host]:port" or "host:port" to pair<"host", "port">.
+ */
+OPENDHT_PUBLIC std::pair<std::string, std::string>
+splitPort(const std::string& s);
+
 class OPENDHT_PUBLIC DhtException : public std::runtime_error {
 public:
     DhtException(const std::string &str = "") :
diff --git a/src/dht_proxy_client.cpp b/src/dht_proxy_client.cpp
index e2dde088e5050d656f585108fd95281c4b5f6a98..41b2d6deba00e0b95791d9afd05b7101661e5e26 100644
--- a/src/dht_proxy_client.cpp
+++ b/src/dht_proxy_client.cpp
@@ -23,6 +23,7 @@
 
 #include "dhtrunner.h"
 #include "op_cache.h"
+#include "utils.h"
 
 #include <restbed>
 #include <json/json.h>
@@ -452,15 +453,8 @@ DhtProxyClient::getProxyInfos()
     }
 
     // A node can have a Ipv4 and a Ipv6. So, we need to retrieve all public ips
-    std::string host, service;
-    auto serviceMarker = serverHost_.find(':');
-    if (serviceMarker != std::string::npos) {
-        host = serverHost_.substr(0, serviceMarker - 1);
-        service = serverHost_.substr(serviceMarker + 1);
-    } else {
-        host = serverHost_;
-    }
-    auto resolved_proxies = SockAddr::resolve(host, service);
+    auto hostAndService = splitPort(serverHost_);
+    auto resolved_proxies = SockAddr::resolve(hostAndService.first, hostAndService.second);
     auto serverHost = serverHost_;
 
     // Try to contact the proxy and set the status to connected when done.
@@ -551,10 +545,8 @@ SockAddr
 DhtProxyClient::parsePublicAddress(const Json::Value& val)
 {
     auto public_ip = val.asString();
-    auto endIp = public_ip.find_last_of(':');
-    auto marker = (public_ip.size() > 0 && public_ip[0] == '[') ? 1 : 0;
-    std::string address = public_ip.substr(marker, endIp - marker * 2);
-    auto sa = SockAddr::resolve(address);
+    auto hostAndService = splitPort(public_ip);
+    auto sa = SockAddr::resolve(hostAndService.first);
     if (sa.empty()) return {};
     return sa.front().getMappedIPv4();
 }
diff --git a/src/utils.cpp b/src/utils.cpp
index c9a7abfd02015fd82778bf77985e3a21a7d4a3b3..93abc1f76ddc866688a5be54a177f1f0f0a3b8bd 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -29,6 +29,26 @@ namespace dht {
 
 static constexpr std::array<uint8_t, 12> MAPPED_IPV4_PREFIX {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}};
 
+std::pair<std::string, std::string>
+splitPort(const std::string& s) {
+    if (s.empty())
+        return {};
+    if (s[0] == '[') {
+        std::size_t closure = s.find_first_of(']');
+        std::size_t found = s.find_last_of(':');
+        if (closure == std::string::npos)
+            return {s, ""};
+        if (found == std::string::npos or found < closure)
+            return {s.substr(1,closure-1), ""};
+        return {s.substr(1,closure-1), s.substr(found+1)};
+    }
+    std::size_t found = s.find_last_of(':');
+    std::size_t first = s.find_first_of(':');
+    if (found == std::string::npos or found != first)
+        return {s, ""};
+    return {s.substr(0,found), s.substr(found+1)};
+}
+
 std::vector<SockAddr>
 SockAddr::resolve(const std::string& host, const std::string& service)
 {
diff --git a/tools/tools_common.h b/tools/tools_common.h
index b51cb60ab12344033ad409f0afbee42168066bad..92c2af5d8ceee703d6dc6640b46fa2e4459a9e02 100644
--- a/tools/tools_common.h
+++ b/tools/tools_common.h
@@ -45,29 +45,6 @@
 #include <sstream>
 #include <fstream>
 
-/**
- * Split "[host]:port" or "host:port" to pair<"host", "port">.
- */
-std::pair<std::string, std::string>
-splitPort(const std::string& s) {
-    if (s.empty())
-        return {};
-    if (s[0] == '[') {
-        std::size_t closure = s.find_first_of(']');
-        std::size_t found = s.find_last_of(':');
-        if (closure == std::string::npos)
-            return {s, ""};
-        if (found == std::string::npos or found < closure)
-            return {s.substr(1,closure-1), ""};
-        return {s.substr(1,closure-1), s.substr(found+1)};
-    }
-    std::size_t found = s.find_last_of(':');
-    std::size_t first = s.find_first_of(':');
-    if (found == std::string::npos or found != first)
-        return {s, ""};
-    return {s.substr(0,found), s.substr(found+1)};
-}
-
 /*
  * The mapString shall have the following format:
  *
@@ -181,7 +158,7 @@ parseArgs(int argc, char **argv) {
             params.network = strtoul(optarg, nullptr, 0);
             break;
         case 'b':
-            params.bootstrap = splitPort((optarg[0] == '=') ? optarg+1 : optarg);
+            params.bootstrap = dht::splitPort((optarg[0] == '=') ? optarg+1 : optarg);
             if (not params.bootstrap.first.empty() and params.bootstrap.second.empty()) {
                 params.bootstrap.second = std::to_string(DHT_DEFAULT_PORT);
             }