Permalink
Browse files

net: Support ipv6 lookups.

We try to connect() to both, so should still be safe in environments where
ipv6 is broken.
  • Loading branch information...
unknownbrackets committed May 1, 2018
1 parent 07e178a commit ca4340b9e06067f36bbac9a7eee5f5319b62904e
View
@@ -69,18 +69,28 @@ static ServerStatus RetrieveStatus() {
// relay that address to a mobile device searching for the server.
static void RegisterServer(int port) {
http::Client http;
Buffer theVoid;
if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) {
char resource[1024] = {};
// We register both IPv4 and IPv6 in case the other client is using a different one.
// Our server is (currently?) ipv4 only, so we always register the ipv4 local for now.
if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT, net::DNSType::IPV4)) {
Buffer theVoid;
if (http.Connect(2, 20.0, &scanCancelled)) {
char resource[1024] = {};
std::string ip = fd_util::GetLocalIP(http.sock());
snprintf(resource, sizeof(resource) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port);
http.GET(resource, &theVoid);
http.Disconnect();
}
}
if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT, net::DNSType::IPV6)) {
Buffer theVoid;
if (http.Connect()) {
http.GET(resource, &theVoid);
http.Disconnect();
}
}
}
static void ExecuteServer() {
@@ -46,7 +46,7 @@ inline unsigned short myhtons(unsigned short x) {
return (x >> 8) | (x << 8);
}
bool Connection::Resolve(const char *host, int port) {
bool Connection::Resolve(const char *host, int port, DNSType type) {
if ((intptr_t)sock_ != -1) {
ELOG("Resolve: Already have a socket");
return false;
@@ -63,7 +63,7 @@ bool Connection::Resolve(const char *host, int port) {
snprintf(port_str, sizeof(port_str), "%d", port);
std::string err;
if (!net::DNSResolve(host, port_str, &resolved_, err)) {
if (!net::DNSResolve(host, port_str, &resolved_, err, type)) {
ELOG("Failed to resolve host %s: %s", host, err.c_str());
// So that future calls fail.
port_ = 0;
@@ -87,10 +87,10 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) {
FD_ZERO(&fds);
for (addrinfo *possible = resolved_; possible != nullptr; possible = possible->ai_next) {
// TODO: Could support ipv6 without huge difficulty...
if (possible->ai_family != AF_INET)
if (possible->ai_family != AF_INET && possible->ai_family != AF_INET6)
continue;
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int sock = socket(possible->ai_family, SOCK_STREAM, IPPROTO_TCP);
if ((intptr_t)sock == -1) {
ELOG("Bad socket");
continue;
@@ -6,6 +6,7 @@
#include "base/basictypes.h"
#include "base/buffer.h"
#include "net/resolve.h"
#ifdef _WIN32
#ifndef NOMINMAX
@@ -28,7 +29,7 @@ class Connection {
virtual ~Connection();
// Inits the sockaddr_in.
bool Resolve(const char *host, int port);
bool Resolve(const char *host, int port, DNSType type = DNSType::ANY);
bool Connect(int maxTries = 2, double timeout = 20.0f, bool *cancelConnect = nullptr);
void Disconnect();
@@ -85,7 +85,7 @@ class Server {
virtual void HandleRequest(const Request &request);
int Port() {
return port_;
return port_;
}
private:
@@ -77,7 +77,7 @@ char *DNSResolve(const char *host)
return ip;
}
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error)
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type)
{
addrinfo hints = {0};
// TODO: Might be uses to lookup other values.
@@ -89,7 +89,11 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo **
// http://stackoverflow.com/questions/1408030/what-is-the-purpose-of-the-ai-v4mapped-flag-in-getaddrinfo
hints.ai_flags = /*AI_V4MAPPED |*/ AI_ADDRCONFIG;
#endif
hints.ai_protocol = IPPROTO_TCP;
hints.ai_protocol = 0;
if (type == DNSType::IPV4)
hints.ai_family = AF_INET;
else if (type == DNSType::IPV6)
hints.ai_family = AF_INET6;
const char *servicep = service.length() == 0 ? NULL : service.c_str();
View
@@ -14,7 +14,13 @@ void Shutdown();
char *DNSResolveTry(const char *host, const char **err);
char *DNSResolve(const char *host);
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error);
enum class DNSType {
ANY = 0,
IPV4 = 1,
IPV6 = 2,
};
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type = DNSType::ANY);
void DNSResolveFree(addrinfo *res);
int inet_pton(int af, const char* src, void* dst);

0 comments on commit ca4340b

Please sign in to comment.