From 2f5d3b1bbdd1b634ec5d387ddae4f2211ffeadcc Mon Sep 17 00:00:00 2001 From: lganzzzo Date: Sat, 6 Apr 2019 19:00:55 +0300 Subject: [PATCH] use getaddrinfo for SimpleTCPConnectionProvider --- .../client/SimpleTCPConnectionProvider.cpp | 79 ++++++++++++------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp b/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp index 3579b764..e2affb54 100644 --- a/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp +++ b/src/oatpp/network/client/SimpleTCPConnectionProvider.cpp @@ -45,27 +45,55 @@ SimpleTCPConnectionProvider::SimpleTCPConnectionProvider(const oatpp::String& ho } std::shared_ptr SimpleTCPConnectionProvider::getConnection(){ - - struct hostent* host = gethostbyname((const char*) m_host->getData()); - struct sockaddr_in client; - - if ((host == NULL) || (host->h_addr == NULL)) { - OATPP_LOGD("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]", "Error. Can't retrieve DNS information."); - return nullptr; + + auto portStr = oatpp::utils::conversion::int32ToStr(m_port); + + struct addrinfo hints; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + hints.ai_protocol = 0; + + struct addrinfo* result; + auto res = getaddrinfo(m_host->c_str(), portStr->c_str(), &hints, &result); + + if (res != 0) { + throw std::runtime_error("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]. Error. Call to getaddrinfo() faild."); } - - bzero(&client, sizeof(client)); - client.sin_family = AF_INET; - client.sin_port = htons(m_port); - memcpy(&client.sin_addr, host->h_addr, host->h_length); - - oatpp::data::v_io_handle clientHandle = socket(AF_INET, SOCK_STREAM, 0); - - if (clientHandle < 0) { - OATPP_LOGD("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]", "Error. Can't create socket."); - return nullptr; + + if (result == nullptr) { + throw std::runtime_error("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]. Error. Call to getaddrinfo() returned no results."); } - + + struct addrinfo* currResult = result; + oatpp::data::v_io_handle clientHandle =- 1; + + while(currResult != nullptr) { + + clientHandle = socket(currResult->ai_family, currResult->ai_socktype, currResult->ai_protocol); + + if(clientHandle >= 0) { + + if(connect(clientHandle, currResult->ai_addr, currResult->ai_addrlen) == 0) { + break; + } else { + ::close(clientHandle); + } + + } + + currResult = currResult->ai_next; + + } + + freeaddrinfo(result); + + if(currResult == nullptr) { + throw std::runtime_error("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]: Error. Can't connect."); + } + #ifdef SO_NOSIGPIPE int yes = 1; v_int32 ret = setsockopt(clientHandle, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(int)); @@ -73,15 +101,9 @@ std::shared_ptr SimpleTCPConnectionProvider::getC OATPP_LOGD("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]", "Warning. Failed to set %s for socket", "SO_NOSIGPIPE"); } #endif - - if (connect(clientHandle, (struct sockaddr *)&client, sizeof(client)) != 0 ) { - ::close(clientHandle); - OATPP_LOGD("[oatpp::network::client::SimpleTCPConnectionProvider::getConnection()]", "Error. Could not connect."); - return nullptr; - } - + return oatpp::network::Connection::createShared(clientHandle); - + } oatpp::async::CoroutineStarterForResult&> SimpleTCPConnectionProvider::getConnectionAsync() { @@ -146,7 +168,8 @@ oatpp::async::CoroutineStarterForResultai_family, m_currentResult->ai_socktype, m_currentResult->ai_protocol); if (m_clientHandle < 0) { - return error("[oatpp::network::client::SimpleTCPConnectionProvider::getConnectionAsync()]: Error. Can't create socket."); + m_currentResult = m_currentResult->ai_next; + return repeat(); } fcntl(m_clientHandle, F_SETFL, O_NONBLOCK);