Skip to content

Commit e31106b

Browse files
authored
Merge pull request #2442 from mavlink/pr-v2.12-pr-hostname-to-ip
[BACKPORT v2.12] core: always convert hostname to IP for UDP remotes
2 parents a82b297 + 6fed725 commit e31106b

File tree

5 files changed

+116
-2
lines changed

5 files changed

+116
-2
lines changed

src/mavsdk/core/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ target_sources(mavsdk
2323
system_impl.cpp
2424
flight_mode.cpp
2525
fs_utils.cpp
26+
hostname_to_ip.cpp
2627
inflate_lzma.cpp
2728
math_conversions.cpp
2829
mavsdk.cpp
@@ -82,8 +83,9 @@ if (NOT BUILD_WITHOUT_CURL)
8283
)
8384

8485
list(APPEND UNIT_TEST_SOURCES
85-
# TODO: add this again
8686
${PROJECT_SOURCE_DIR}/mavsdk/core/curl_test.cpp
87+
${PROJECT_SOURCE_DIR}/mavsdk/core/hostname_to_ip_test.cpp
88+
# TODO: add this again
8789
#${PROJECT_SOURCE_DIR}/mavsdk/core/http_loader_test.cpp
8890
)
8991
else()

src/mavsdk/core/hostname_to_ip.cpp

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include "hostname_to_ip.h"
2+
#include "log.h"
3+
4+
#if defined(WINDOWS)
5+
#include <winsock2.h>
6+
#include <ws2tcpip.h>
7+
#pragma comment(lib, "ws2_32.lib")
8+
#else
9+
#include <netdb.h>
10+
#include <arpa/inet.h>
11+
#include <sys/types.h>
12+
#include <sys/socket.h>
13+
#endif
14+
15+
namespace mavsdk {
16+
17+
std::optional<std::string> resolve_hostname_to_ip(const std::string& hostname)
18+
{
19+
#if defined(WINDOWS)
20+
WSADATA wsaData;
21+
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
22+
std::cerr << "WSAStartup failed" << std::endl;
23+
return {};
24+
}
25+
#endif
26+
27+
addrinfo hints{};
28+
hints.ai_family = AF_INET; // IPv4
29+
hints.ai_socktype = SOCK_STREAM;
30+
hints.ai_flags = AI_PASSIVE;
31+
32+
addrinfo* result = nullptr;
33+
int res = getaddrinfo(hostname.c_str(), nullptr, &hints, &result);
34+
if (res != 0) {
35+
#if defined(WINDOWS)
36+
LogErr() << "getaddrinfo failed: " << WSAGetLastError();
37+
WSACleanup();
38+
#else
39+
LogErr() << "getaddrinfo failed: " << gai_strerror(res);
40+
#endif
41+
return {};
42+
}
43+
44+
std::string ipAddress;
45+
for (addrinfo* ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
46+
sockaddr_in* sockaddrIpv4 = reinterpret_cast<sockaddr_in*>(ptr->ai_addr);
47+
char ipStr[INET_ADDRSTRLEN];
48+
inet_ntop(AF_INET, &(sockaddrIpv4->sin_addr), ipStr, INET_ADDRSTRLEN);
49+
ipAddress = ipStr;
50+
break; // Take the first result
51+
}
52+
53+
freeaddrinfo(result);
54+
#if defined(WINDOWS)
55+
WSACleanup();
56+
#endif
57+
return {ipAddress};
58+
}
59+
60+
} // namespace mavsdk

src/mavsdk/core/hostname_to_ip.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <optional>
5+
6+
namespace mavsdk {
7+
8+
std::optional<std::string> resolve_hostname_to_ip(const std::string& hostname);
9+
10+
} // namespace mavsdk
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "hostname_to_ip.h"
2+
#include <gtest/gtest.h>
3+
4+
using namespace mavsdk;
5+
6+
TEST(HostnameToIp, Localhost)
7+
{
8+
auto host = "localhost";
9+
auto ip = resolve_hostname_to_ip(host);
10+
ASSERT_TRUE(ip);
11+
EXPECT_EQ(ip.value(), "127.0.0.1");
12+
}
13+
14+
TEST(HostnameToIp, Ip)
15+
{
16+
auto host = "127.0.0.1";
17+
auto ip = resolve_hostname_to_ip(host);
18+
ASSERT_TRUE(ip);
19+
EXPECT_EQ(ip.value(), host);
20+
}
21+
22+
TEST(HostnameToIp, Empty)
23+
{
24+
auto host = "";
25+
auto ip = resolve_hostname_to_ip(host);
26+
EXPECT_FALSE(ip);
27+
}
28+
29+
TEST(HostnameToIp, Something)
30+
{
31+
auto host = "something";
32+
auto ip = resolve_hostname_to_ip(host);
33+
EXPECT_FALSE(ip);
34+
}

src/mavsdk/core/mavsdk_impl.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "server_component_impl.h"
1515
#include "mavlink_channels.h"
1616
#include "callback_list.tpp"
17+
#include "hostname_to_ip.h"
1718

1819
namespace mavsdk {
1920

@@ -573,7 +574,14 @@ std::pair<ConnectionResult, Mavsdk::ConnectionHandle> MavsdkImpl::setup_udp_remo
573574
}
574575
ConnectionResult ret = new_conn->start();
575576
if (ret == ConnectionResult::Success) {
576-
new_conn->add_remote(remote_ip, remote_port);
577+
// We need to add the IP rather than a hostname, otherwise we end up with two remotes:
578+
// one for the IP, and one for a hostname.
579+
auto always_ip = resolve_hostname_to_ip(remote_ip);
580+
581+
if (!always_ip) {
582+
return {ConnectionResult::DestinationIpUnknown, Mavsdk::ConnectionHandle{}};
583+
}
584+
new_conn->add_remote(always_ip.value(), remote_port);
577585
auto handle = add_connection(new_conn);
578586
std::lock_guard<std::recursive_mutex> lock(_systems_mutex);
579587

0 commit comments

Comments
 (0)