Skip to content

Commit

Permalink
Added hosted_at. (Resolve #1113)
Browse files Browse the repository at this point in the history
  • Loading branch information
yhirose committed Dec 31, 2021
1 parent 27d128b commit 65a8f4c
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 10 deletions.
67 changes: 57 additions & 10 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1657,6 +1657,10 @@ Client::set_write_timeout(const std::chrono::duration<Rep, Period> &duration) {
* .h + .cc.
*/

std::string hosted_at(const char *hostname);

void hosted_at(const char *hostname, std::vector<std::string> &addrs);

std::string append_query_params(const char *path, const Params &params);

std::pair<std::string, std::string> make_range_header(Ranges ranges);
Expand Down Expand Up @@ -2499,25 +2503,28 @@ socket_t create_socket(const char *host, const char *ip, int port,
SocketOptions socket_options,
BindOrConnect bind_or_connect) {
// Get address info
const char *node = nullptr;
struct addrinfo hints;
struct addrinfo *result;

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = address_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = socket_flags;
hints.ai_protocol = 0;

// Ask getaddrinfo to convert IP in c-string to address
if (ip[0] != '\0') {
node = ip;
// Ask getaddrinfo to convert IP in c-string to address
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
} else {
node = host;
hints.ai_family = address_family;
hints.ai_flags = socket_flags;
}

auto service = std::to_string(port);

if (ip[0] != '\0' ? getaddrinfo(ip, service.c_str(), &hints, &result)
: getaddrinfo(host, service.c_str(), &hints, &result)) {
if (getaddrinfo(node, service.c_str(), &hints, &result)) {
#if defined __linux__ && !defined __ANDROID__
res_init();
#endif
Expand Down Expand Up @@ -2728,22 +2735,27 @@ inline socket_t create_client_socket(
return sock;
}

inline void get_remote_ip_and_port(const struct sockaddr_storage &addr,
inline bool get_remote_ip_and_port(const struct sockaddr_storage &addr,
socklen_t addr_len, std::string &ip,
int &port) {
if (addr.ss_family == AF_INET) {
port = ntohs(reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_port);
} else if (addr.ss_family == AF_INET6) {
port =
ntohs(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_port);
} else {
return false;
}

std::array<char, NI_MAXHOST> ipstr{};
if (!getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
0, NI_NUMERICHOST)) {
ip = ipstr.data();
if (getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
0, NI_NUMERICHOST)) {
return false;
}

ip = ipstr.data();
return true;
}

inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) {
Expand Down Expand Up @@ -4304,6 +4316,41 @@ class ContentProviderAdapter {

} // namespace detail

inline std::string hosted_at(const char *hostname) {
std::vector<std::string> addrs;
hosted_at(hostname, addrs);
if (addrs.empty()) { return std::string(); }
return addrs[0];
}

inline void hosted_at(const char *hostname, std::vector<std::string> &addrs) {
struct addrinfo hints;
struct addrinfo *result;

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;

if (getaddrinfo(hostname, nullptr, &hints, &result)) {
#if defined __linux__ && !defined __ANDROID__
res_init();
#endif
return;
}

for (auto rp = result; rp; rp = rp->ai_next) {
const auto &addr =
*reinterpret_cast<struct sockaddr_storage *>(rp->ai_addr);
std::string ip;
int dummy = -1;
if (detail::get_remote_ip_and_port(addr, sizeof(struct sockaddr_storage),
ip, dummy)) {
addrs.push_back(ip);
}
}
}

inline std::string append_query_params(const char *path, const Params &params) {
std::string path_with_query = path;
const static std::regex re("[^?]+\\?.*");
Expand Down
30 changes: 30 additions & 0 deletions test/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,36 @@ TEST(ChunkedEncodingTest, FromHTTPWatch_Online) {
EXPECT_EQ(out, res->body);
}

TEST(HostnameToIPConversionTest, HTTPWatch_Online) {
auto host = "www.httpwatch.com";

{
auto ip = hosted_at(host);
EXPECT_EQ("191.236.16.12", ip);
}

{
std::vector<std::string> addrs;
hosted_at(host, addrs);
EXPECT_EQ(1u, addrs.size());
}
}

TEST(HostnameToIPConversionTest, YouTube_Online) {
auto host = "www.youtube.com";

{
auto ip = hosted_at(host);
EXPECT_EQ("2607:f8b0:4006:809::200e", ip);
}

{
std::vector<std::string> addrs;
hosted_at(host, addrs);
EXPECT_EQ(20u, addrs.size());
}
}

TEST(ChunkedEncodingTest, WithContentReceiver_Online) {
auto host = "www.httpwatch.com";

Expand Down

0 comments on commit 65a8f4c

Please sign in to comment.