Lets assume that I have used getaddrinfo
and resolved an address successfully:
//...
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0)
return -1;
if (result != nullptr) {
// ....
}
freeaddrinfo(result);
in this case, result->ai_addr
and result->ai_addrlen
refer to a sockaddr
structure and its size(which is based on its type). Now assume that we want to duplicate this sockaddr
in C . What is the best valid approach to do so? I wrote this code, but I'm not sure if it is UB-free:
auto deleter = [](void* buf) { if (buf) free(buf); };
auto buf = malloc(result->ai_addrlen);
if (buf) {
memcpy(buf, result->ai_addr, result->ai_addrlen);
}
std::unique_ptr<sockaddr, decltype(deleter)> myptr(static_cast<sockaddr*>(buf), deleter);
Is this a valid C code?
CodePudding user response:
It seems valid to me. If you want to avoid dynamic allocations, you could also limit yourself to a union of all supported address families. Something like this:
union NetworkAddress
{
sockaddr addr;
sockaddr_in in4;
sockaddr_in6 in6;
static NetworkAddress from_addrinfo(const addrinfo* addr)
{
NetworkAddress rtrn;
if(addr->ai_addrlen <= sizeof(rtrn))
std::memcpy(&rtrn, addr->ai_addr, addr->ai_addrlen);
else
throw std::runtime_error("Unsupported network address");
return rtrn;
}
};
CodePudding user response:
Why reinvent the wheel? Use boost::asio
(and use vcpkg to install it).
// create address from string
auto someaddress=boost::asio::make_address("127.0.0.1");
// make a copy
boost::asio::ip::address copy=someaddress;