#include "address_info.hpp" #include #ifndef _WIN32 #include #endif #include "net.hpp" #include #include #include namespace llarp { bool operator==(const AddressInfo& lhs, const AddressInfo& rhs) { // we don't care about rank return lhs.pubkey == rhs.pubkey && lhs.port == rhs.port && lhs.dialect == rhs.dialect && lhs.ip == rhs.ip; } bool operator<(const AddressInfo& lhs, const AddressInfo& rhs) { return std::tie(lhs.rank, lhs.ip, lhs.port) < std::tie(rhs.rank, rhs.ip, rhs.port); } std::variant AddressInfo::IP() const { return SockAddr{ip}.getIP(); } bool AddressInfo::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { uint64_t i; char tmp[128] = {0}; llarp_buffer_t strbuf; // rank if (key.startswith("c")) { if (!bencode_read_integer(buf, &i)) return false; if (i > 65536 || i <= 0) return false; rank = i; return true; } // dialect if (key.startswith("d")) { if (!bencode_read_string(buf, &strbuf)) return false; if (strbuf.sz > sizeof(tmp)) return false; memcpy(tmp, strbuf.base, strbuf.sz); tmp[strbuf.sz] = 0; dialect = std::string(tmp); return true; } // encryption public key if (key.startswith("e")) { return pubkey.BDecode(buf); } // ip address if (key.startswith("i")) { if (!bencode_read_string(buf, &strbuf)) return false; if (strbuf.sz >= sizeof(tmp)) return false; memcpy(tmp, strbuf.base, strbuf.sz); tmp[strbuf.sz] = 0; return inet_pton(AF_INET6, tmp, &ip.s6_addr[0]) == 1; } // port if (key.startswith("p")) { if (!bencode_read_integer(buf, &i)) return false; if (i > 65536 || i <= 0) return false; port = i; return true; } // version if (key.startswith("v")) { if (!bencode_read_integer(buf, &i)) return false; return i == llarp::constants::proto_version; } // bad key return false; } std::string AddressInfo::bt_encode() const { char ipbuff[128] = {0}; oxenc::bt_dict_producer btdp; try { btdp.append("c", rank); btdp.append("d", dialect); btdp.append("e", pubkey.ToView()); const char* ipstr = inet_ntop(AF_INET6, (void*)&ip, ipbuff, sizeof(ipbuff)); btdp.append("i", std::string_view{ipstr, strnlen(ipstr, sizeof(ipbuff))}); btdp.append("p", port); btdp.append("v", version); } catch (...) { log::critical(net_cat, "Error: AddressInfo failed to bt encode contents!"); } return std::move(btdp).str(); } IpAddress AddressInfo::toIpAddress() const { SockAddr addr(ip); addr.setPort(port); return {addr}; } void AddressInfo::fromSockAddr(const SockAddr& addr) { const auto* addr6 = static_cast(addr); memcpy(ip.s6_addr, addr6->sin6_addr.s6_addr, sizeof(ip.s6_addr)); port = addr.getPort(); } std::string AddressInfo::ToString() const { char tmp[INET6_ADDRSTRLEN] = {0}; inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp)); return fmt::format("[{}]:{}", tmp, port); } std::string AddressInfo::IPString() const { char tmp[INET6_ADDRSTRLEN] = {0}; inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp)); return std::string{tmp}; } void to_json(nlohmann::json& j, const AddressInfo& a) { char tmp[128] = {0}; inet_ntop(AF_INET6, (void*)&a.ip, tmp, sizeof(tmp)); j = nlohmann::json{ {"rank", a.rank}, {"dialect", a.dialect}, {"pubkey", a.pubkey.ToString()}, {"in6_addr", tmp}, {"port", a.port}}; } } // namespace llarp