Skip to content

Commit 2bbd8d7

Browse files
Swap to using getnameinfo for address names (#177)
getnameinfo is much better at converting socket addresses to strings, it can resolve hostnames etc as well. Swap to using it for `sockt_t.address()` and just pass the sock_t objects through to consumers so they can decide how to work with them.
1 parent bf1a7bd commit 2bbd8d7

4 files changed

Lines changed: 38 additions & 57 deletions

File tree

src/dsl/word/TCP.hpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,10 @@ namespace dsl {
6666

6767
struct Connection {
6868

69-
struct Target {
70-
/// The address of the connection
71-
std::string address;
72-
/// The port of the connection
73-
uint16_t port;
74-
};
75-
7669
/// The local address of the connection
77-
Target local;
70+
util::network::sock_t local;
7871
/// The remote address of the connection
79-
Target remote;
72+
util::network::sock_t remote;
8073

8174
/// The file descriptor for the connection
8275
fd_t fd;
@@ -187,10 +180,7 @@ namespace dsl {
187180
return Connection{};
188181
}
189182

190-
auto local_s = local.address();
191-
auto remote_s = remote.address();
192-
193-
return Connection{{local_s.first, local_s.second}, {remote_s.first, remote_s.second}, fd.release()};
183+
return Connection{local, remote, fd.release()};
194184
}
195185
};
196186

src/dsl/word/UDP.hpp

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,10 @@ namespace dsl {
102102
/// If the packet is valid (it contains data)
103103
bool valid{false};
104104

105-
struct Target {
106-
Target() = default;
107-
Target(std::string address, const uint16_t& port) : address(std::move(address)), port(port) {}
108-
109-
/// The address of the target
110-
std::string address;
111-
/// The port of the target
112-
uint16_t port{0};
113-
};
114-
115105
/// The information about this packets destination
116-
Target local;
106+
util::network::sock_t local{};
117107
/// The information about this packets source
118-
Target remote;
108+
util::network::sock_t remote{};
119109

120110
/// The data to be sent in the packet
121111
std::vector<uint8_t> payload;
@@ -427,12 +417,10 @@ namespace dsl {
427417
RecvResult result = read<DSL>(task);
428418

429419
Packet p{};
430-
p.valid = result.valid;
431-
p.payload = std::move(result.payload);
432-
auto local_s = result.local.address();
433-
auto remote_s = result.remote.address();
434-
p.local = Packet::Target{local_s.first, local_s.second};
435-
p.remote = Packet::Target{remote_s.first, remote_s.second};
420+
p.valid = result.valid;
421+
p.payload = std::move(result.payload);
422+
p.local = result.local;
423+
p.remote = result.remote;
436424

437425
// Confirm that this packet was sent to one of our local addresses
438426
for (const auto& iface : util::network::get_interfaces()) {
@@ -475,12 +463,10 @@ namespace dsl {
475463
if (result.local.sock.sa_family == AF_INET) {
476464

477465
Packet p{};
478-
p.valid = result.valid;
479-
p.payload = std::move(result.payload);
480-
auto local_s = result.local.address();
481-
auto remote_s = result.remote.address();
482-
p.local = Packet::Target{local_s.first, local_s.second};
483-
p.remote = Packet::Target{remote_s.first, remote_s.second};
466+
p.valid = result.valid;
467+
p.payload = std::move(result.payload);
468+
p.local = result.local;
469+
p.remote = result.remote;
484470

485471
// 255.255.255.255 is always a valid broadcast address
486472
if (result.local.ipv4.sin_addr.s_addr == htonl(INADDR_BROADCAST)) {
@@ -526,12 +512,10 @@ namespace dsl {
526512
// Only return multicast packets
527513
if (multicast) {
528514
Packet p{};
529-
p.valid = result.valid;
530-
p.payload = std::move(result.payload);
531-
auto local_s = result.local.address();
532-
auto remote_s = result.remote.address();
533-
p.local = Packet::Target{local_s.first, local_s.second};
534-
p.remote = Packet::Target{remote_s.first, remote_s.second};
515+
p.valid = result.valid;
516+
p.payload = std::move(result.payload);
517+
p.local = result.local;
518+
p.remote = result.remote;
535519
return p;
536520
}
537521

src/util/network/sock_t.hpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
#define NUCLEAR_UTIL_NETWORK_SOCK_T_HPP
2525

2626
#include <array>
27+
#include <cstring>
2728
#include <stdexcept>
29+
#include <system_error>
2830

2931
#include "../platform.hpp"
3032

@@ -50,19 +52,23 @@ namespace util {
5052
}
5153
}
5254

53-
std::pair<std::string, in_port_t> address() const {
54-
std::array<char, std::max(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)> c = {0};
55-
switch (sock.sa_family) {
56-
case AF_INET:
57-
return std::make_pair(::inet_ntop(sock.sa_family, &ipv4.sin_addr, c.data(), c.size()),
58-
ntohs(ipv4.sin_port));
59-
case AF_INET6:
60-
return std::make_pair(::inet_ntop(sock.sa_family, &ipv6.sin6_addr, c.data(), c.size()),
61-
ntohs(ipv6.sin6_port));
62-
default:
63-
throw std::runtime_error("Cannot get address for socket address family "
64-
+ std::to_string(sock.sa_family));
55+
std::pair<std::string, in_port_t> address(bool numeric_host = false) const {
56+
std::array<char, NI_MAXHOST> host{};
57+
std::array<char, NI_MAXSERV> service{};
58+
const int result = ::getnameinfo(reinterpret_cast<const sockaddr*>(&storage),
59+
size(),
60+
host.data(),
61+
static_cast<socklen_t>(host.size()),
62+
service.data(),
63+
static_cast<socklen_t>(service.size()),
64+
NI_NUMERICSERV | (numeric_host ? NI_NUMERICHOST : 0));
65+
if (result != 0) {
66+
throw std::system_error(
67+
network_errno,
68+
std::system_category(),
69+
"Cannot get address for socket address family " + std::to_string(sock.sa_family));
6570
}
71+
return std::make_pair(std::string(host.data()), static_cast<in_port_t>(std::stoi(service.data())));
6672
}
6773
};
6874

tests/tests/dsl/UDP.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,9 @@ class TestReactor : public test_util::TestBase<TestReactor> {
174174
void handle_data(const std::string& name, const UDP::Packet& packet) {
175175
const std::string data(packet.payload.begin(), packet.payload.end());
176176

177-
// Convert IP address to string in dotted decimal format
178-
const std::string local = packet.local.address + ":" + std::to_string(packet.local.port);
177+
// Convert IP address to a numeric string
178+
auto s = packet.local.address(true);
179+
const std::string local = s.first + ":" + std::to_string(s.second);
179180

180181
events.push_back(name + " <- " + data + " (" + local + ")");
181182

0 commit comments

Comments
 (0)