Begin implementing SockAddr

pull/1257/head
Stephen Shelton 4 years ago
parent bcf473757d
commit 0b54087689
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -150,6 +150,8 @@ set(LIB_SRC
messages/relay_commit.cpp
messages/relay_status.cpp
net/address_info.cpp
net/ip_address.cpp
net/sock_addr.cpp
net/exit_info.cpp
nodedb.cpp
path/ihophandler.cpp

@ -162,7 +162,7 @@ llarp_tcp_async_try_connect(struct llarp_ev_loop* loop, struct llarp_tcp_connect
bool
llarp_tcp_serve(
struct llarp_ev_loop* loop, struct llarp_tcp_acceptor* tcp, const struct sockaddr* bindaddr)
struct llarp_ev_loop* loop, struct llarp_tcp_acceptor* tcp, const llarp::SockAddr& bindaddr)
{
tcp->loop = loop;
return loop->tcp_listen(tcp, bindaddr);

@ -423,7 +423,7 @@ namespace libuv
{
udp_glue* glue = static_cast<udp_glue*>(handle->data);
if (addr)
glue->RecvFrom(nread, buf, llarp::SockAddr(addr));
glue->RecvFrom(nread, buf, llarp::SockAddr(*addr));
if (nread <= 0 || glue->m_UDP == nullptr || glue->m_UDP->recvfrom != nullptr)
delete[] buf->base;
}

@ -1,4 +1,5 @@
#include <net/address_info.hpp>
#include <stdexcept>
#ifndef _WIN32
#include <arpa/inet.h>
@ -148,6 +149,18 @@ namespace llarp
return bencode_end(buff);
}
IpAddress
AddressInfo::toIpAddress() const
{
throw std::runtime_error("FIXME");
}
void
AddressInfo::fromIpAddress(const IpAddress& address)
{
throw std::runtime_error("FIXME");
}
std::ostream&
AddressInfo::print(std::ostream& stream, int level, int spaces) const
{

@ -0,0 +1,98 @@
#include <net/ip_address.hpp>
namespace llarp
{
IpAddress::IpAddress(std::string_view str)
{
throw std::runtime_error("FIXME");
}
IpAddress::IpAddress(std::string_view str, std::optional<uint16_t> port)
{
throw std::runtime_error("FIXME");
}
IpAddress::IpAddress(const SockAddr& addr)
{
throw std::runtime_error("FIXME");
}
SockAddr&
IpAddress::operator=(const sockaddr& other)
{
throw std::runtime_error("FIXME");
}
std::optional<uint16_t>
IpAddress::getPort() const
{
throw std::runtime_error("FIXME");
}
void
IpAddress::setPort(std::optional<uint16_t> port)
{
throw std::runtime_error("FIXME");
}
void
IpAddress::setAddress(std::string_view str)
{
throw std::runtime_error("FIXME");
}
void
IpAddress::setAddress(std::string_view str, std::optional<uint16_t> port)
{
throw std::runtime_error("FIXME");
}
bool
IpAddress::isIPv4()
{
throw std::runtime_error("FIXME");
}
bool
IpAddress::isEmpty() const
{
throw std::runtime_error("FIXME");
}
SockAddr
IpAddress::createSockAddr() const
{
throw std::runtime_error("FIXME");
}
bool
IpAddress::isBogon() const
{
throw std::runtime_error("FIXME");
}
std::string
IpAddress::toString() const
{
throw std::runtime_error("FIXME");
}
bool
IpAddress::operator<(const IpAddress& other) const
{
throw std::runtime_error("FIXME");
}
bool
IpAddress::operator==(const IpAddress& other) const
{
throw std::runtime_error("FIXME");
}
std::ostream&
operator<<(std::ostream& out, const IpAddress& address)
{
throw std::runtime_error("FIXME");
}
} // namespace llarp

@ -1,6 +1,7 @@
#include <net/net.hpp>
#include <net/net_if.hpp>
#include <stdexcept>
#ifdef ANDROID
#include <android/ifaddrs.h>
@ -427,14 +428,17 @@ namespace llarp
{
if (i->ifa_addr->sa_family == af)
{
llarp::SockAddr a(*i->ifa_addr);
llarp::IpAddress ip(a);
/* TODO: why the fuck does'n this work?
// llarp::SockAddr a(i->ifa_addr);
// llarp::IpAddress ip(a);
if (!ip.isBogon())
{
ifname = i->ifa_name;
found = true;
}
*/
throw std::runtime_error("WTF");
}
}
});
@ -540,7 +544,10 @@ namespace llarp
sockaddr* sptr = (sockaddr*)&s;
if (!llarp_getifaddr(ifname.c_str(), af, sptr))
return std::nullopt;
return IpAddress(SockAddr(sptr));
// TODO: why the fuck does this not compile?
// llarp::SockAddr saddr = SockAddr(*sptr);
// return llarp::IpAddress(saddr);
throw std::runtime_error("WTF");
}
bool
@ -552,7 +559,10 @@ namespace llarp
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
result = IpAddress(SockAddr(addr));
// TODO: why the fuck doesn't this work?
// SockAddr saddr = SockAddr(addr);
// result = IpAddress(saddr);
throw std::runtime_error("WTF");
return true;
}
if (af == AF_INET6)

@ -0,0 +1,199 @@
#include <net/sock_addr.hpp>
#include <netinet/in.h>
#include <util/str.hpp>
#include <util/mem.hpp>
#include <charconv>
#include <stdexcept>
namespace llarp
{
/// shared utility functions
///
void
SockAddr::init()
{
llarp::Zero(&m_addr, sizeof(m_addr));
}
SockAddr::SockAddr()
{
init();
}
SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
init();
setIPv4(a, b, c, d);
}
SockAddr::SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port)
{
init();
setIPv4(a, b, c, d);
setPort(port);
}
SockAddr::SockAddr(std::string_view addr)
{
throw std::runtime_error("FIXME");
}
SockAddr::SockAddr(const SockAddr&)
{
throw std::runtime_error("FIXME");
}
SockAddr&
SockAddr::operator=(const SockAddr&) const
{
throw std::runtime_error("FIXME");
}
SockAddr::SockAddr(const sockaddr& addr)
{
throw std::runtime_error("FIXME");
}
SockAddr::SockAddr(const sockaddr_in& addr)
{
throw std::runtime_error("FIXME");
}
SockAddr::operator const sockaddr*() const
{
throw std::runtime_error("FIXME");
}
void
SockAddr::fromString(std::string_view str)
{
if (str.empty())
throw std::invalid_argument("cannot construct IPv4 from empty string");
// NOTE: this potentially involves multiple memory allocations,
// reimplement without split() if it is performance bottleneck
auto splits = split(str, ':');
// TODO: having ":port" at the end makes this ambiguous with IPv6
// come up with a strategy for implementing
if (splits.size() > 2)
throw std::runtime_error("IPv6 not yet supported");
// split() shouldn't return an empty list if str is empty (checked above)
assert(splits.size() > 0);
// splits[0] should be dot-separated IPv4
auto ipSplits = split(splits[0], '.');
if (ipSplits.size() != 4)
throw std::invalid_argument(stringify(str, " is not a valid IPv4 address"));
uint8_t ipBytes[4] = {0};
for (int i = 0; i < 4; ++i)
{
auto byteStr = ipSplits[i];
auto result = std::from_chars(byteStr.data(), byteStr.data() + byteStr.size(), ipBytes[i]);
if (result.ec == std::errc::invalid_argument)
throw std::runtime_error(stringify(str, " contains invalid number"));
}
// attempt port before setting IPv4 bytes
if (splits.size() == 2)
{
uint16_t port = 0;
auto portStr = splits[1];
auto result = std::from_chars(portStr.data(), portStr.data() + portStr.size(), port);
if (result.ec == std::errc::invalid_argument)
throw std::runtime_error(stringify(str, " contains invalid port"));
setPort(port);
}
setIPv4(ipBytes[0], ipBytes[1], ipBytes[2], ipBytes[3]);
}
std::string
SockAddr::toString() const
{
// TODO: review
if (isEmpty())
return "";
if (m_addr.sin6_family != AF_INET)
throw std::runtime_error("Only IPv4 supported");
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
// ensure SIIT
if (not ip6[10] == 0xff or not ip6[11])
throw std::runtime_error("Only SIIT address supported");
constexpr auto MaxIPv4PlusPortStringSize = 22;
std::string str;
str.reserve(MaxIPv4PlusPortStringSize);
// TODO: ensure these don't each incur a memory allocation
str.append(std::to_string(ip6[12]));
str.append(1, '.');
str.append(std::to_string(ip6[13]));
str.append(1, '.');
str.append(std::to_string(ip6[14]));
str.append(1, '.');
str.append(std::to_string(ip6[15]));
str.append(1, ':');
str.append(std::to_string(m_addr.sin6_port));
return str;
}
bool
SockAddr::isEmpty() const
{
return m_empty;
}
void
SockAddr::setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
m_addr.sin6_family = AF_INET;
uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr));
// SIIT (represent IPv4 with IPv6)
ip6[10] = 0xff;
ip6[11] = 0xff;
ip6[12] = a;
ip6[13] = b;
ip6[14] = c;
ip6[15] = d;
m_empty = false;
}
void
SockAddr::setPort(uint16_t port)
{
m_addr.sin6_port = htons(port);
}
uint16_t
SockAddr::getPort() const
{
return ntohs(m_addr.sin6_port);
}
std::ostream&
operator<<(std::ostream& out, const SockAddr& address)
{
throw std::runtime_error("FIXME");
}
} // namespace llarp

@ -9,31 +9,49 @@ namespace llarp
{
/// A simple SockAddr wrapper which provides a sockaddr_in (IPv4). Memory management is handled
/// in constructor and destructor (if needed) and copying is disabled.
///
/// This is immutable other than assignment operator.
struct SockAddr
{
SockAddr();
SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port);
SockAddr(uint32_t addr);
SockAddr(std::string_view addr);
SockAddr(const SockAddr&);
SockAddr&
operator=(const SockAddr&) const;
SockAddr(const sockaddr* addr);
SockAddr(const sockaddr& addr);
SockAddr(const sockaddr_in* addr);
SockAddr(const sockaddr_in& addr);
operator const sockaddr*() const;
void
fromString(std::string_view str);
std::string
toString() const;
/// Returns true if this is an empty SockAddr, defined by having no IP address set. An empty IP
/// address with a valid port is still considered empty.
///
/// @return true if this is empty, false otherwise
bool
isEmpty() const;
void
setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
void
setPort(uint16_t port);
uint16_t
getPort() const;
private:
sockaddr_in addr;
bool m_empty = true;
sockaddr_in6 m_addr;
void
init();
};
std::ostream&

@ -82,7 +82,8 @@ add_executable(${CATCH_EXE}
util/test_llarp_util_decaying_hashset.cpp
config/test_llarp_config_definition.cpp
config/test_llarp_config_output.cpp
net/test_addr.cpp
net/test_ip_address.cpp
net/test_sock_addr.cpp
check_main.cpp)
target_link_libraries(${CATCH_EXE} PUBLIC ${STATIC_LIB} Catch2::Catch2)

@ -1,13 +0,0 @@
#include <net/net_addr.hpp>
#include <catch2/catch.hpp>
TEST_CASE("Addr FromString", "[addr]")
{
llarp::Addr addr;
bool success = false;
CHECK_NOTHROW(success = addr.FromString("127.0.0.1:53"));
CHECK(success == true);
CHECK(addr.port() == 53);
CHECK(addr.ToString() == "127.0.0.1:53");
}

@ -0,0 +1,9 @@
#include <net/ip_address.hpp>
#include <catch2/catch.hpp>
TEST_CASE("IpAddress empty constructor", "[IpAdress]")
{
llarp::IpAddress address;
CHECK(address.isEmpty() == true);
}

@ -0,0 +1,41 @@
#include <net/sock_addr.hpp>
#include <net/ip_address.hpp>
#include <net/net_if.hpp>
#include <catch2/catch.hpp>
TEST_CASE("SockAddr from sockaddr", "[SockAddr]")
{
sockaddr sa;
// check that this compiles (taking sockaddr by ref)
CHECK_NOTHROW(llarp::SockAddr(sa));
sockaddr* saptr = &sa;
// check that this compiles (taking sockaddr by ref from cast from ptr)
// this was giving odd compilation errors from within net/net.cpp
llarp::SockAddr addr(*saptr);
llarp::IpAddress ip(addr);
}
TEST_CASE("SockAddr from IPv4", "[SockAddr]")
{
llarp::SockAddr addr(1, 2, 3, 4);
CHECK(addr.toString() == "1.2.3.4:0");
}
TEST_CASE("SockAddr test port", "[SockAddr]")
{
llarp::SockAddr addr;
addr.setPort(42);
CHECK(addr.getPort() == 42);
}
TEST_CASE("SockAddr fromString", "[SockAddr]")
{
llarp::SockAddr addr;
CHECK_NOTHROW(addr.fromString("1.2.3.4"));
CHECK(addr.toString() == "1.2.3.4:0");
}

@ -32,6 +32,8 @@ struct AbyssTestBase : public ::testing::Test
void
Start()
{
throw std::runtime_error("FIXME (replace libabyss with lokimq)");
/*
loop = llarp_make_ev_loop();
logic = std::make_shared< llarp::Logic >();
loop->set_logic(logic);
@ -50,6 +52,7 @@ struct AbyssTestBase : public ::testing::Test
}
std::this_thread::sleep_for(1s);
}
*/
}
void

@ -30,6 +30,12 @@ struct RCTest : public test::LlarpTest<>
TEST_F(RCTest, TestSignVerify)
{
// TODO: RouterContact no longer takes a netmask (the nuint32_t below)
// This was previously used in a call to IsBogonRange, but this wasn't actually
// implemented anyway
throw std::runtime_error("FIXME: RouterContact doesn't take a netmask anymore");
/*
NetID netid(DEF_VALUE);
RC_t rc;
SecKey_t encr;
@ -46,4 +52,5 @@ TEST_F(RCTest, TestSignVerify)
ASSERT_TRUE(rc.Sign(sign));
ASSERT_TRUE(rc.Verify(time_now_ms()));
*/
}

Loading…
Cancel
Save