mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-28 02:48:09 +08:00
Move Hostname to its own files. (#6759)
* Change DNS cache to use std::map. Revert commit 90c259d84e95dd35e01149c0a86bd18e82e33930, because if we use unordered_map, toString() can be inconsistent. * Move ClientKnob::COORDINATOR_HOSTNAME_RESOLVE_DELAY to FlowKnob::HOSTNAME_RESOLVE_DELAY. * Move Hostname to its own files. Also, add resolve-related variables and functions in Hostname.
This commit is contained in:
parent
bb9b9d2471
commit
465ff712b6
@ -50,7 +50,6 @@ void ClientKnobs::initialize(Randomize randomize) {
|
|||||||
init( MAX_GENERATIONS_OVERRIDE, 0 );
|
init( MAX_GENERATIONS_OVERRIDE, 0 );
|
||||||
init( MAX_GENERATIONS_SIM, 50 ); //Disable network connections after this many generations in simulation, should be less than RECOVERY_DELAY_START_GENERATION
|
init( MAX_GENERATIONS_SIM, 50 ); //Disable network connections after this many generations in simulation, should be less than RECOVERY_DELAY_START_GENERATION
|
||||||
|
|
||||||
init( COORDINATOR_HOSTNAME_RESOLVE_DELAY, 0.05 );
|
|
||||||
init( COORDINATOR_RECONNECTION_DELAY, 1.0 );
|
init( COORDINATOR_RECONNECTION_DELAY, 1.0 );
|
||||||
init( CLIENT_EXAMPLE_AMOUNT, 20 );
|
init( CLIENT_EXAMPLE_AMOUNT, 20 );
|
||||||
init( MAX_CLIENT_STATUS_AGE, 1.0 );
|
init( MAX_CLIENT_STATUS_AGE, 1.0 );
|
||||||
|
@ -49,7 +49,6 @@ public:
|
|||||||
double MAX_GENERATIONS_OVERRIDE;
|
double MAX_GENERATIONS_OVERRIDE;
|
||||||
double MAX_GENERATIONS_SIM;
|
double MAX_GENERATIONS_SIM;
|
||||||
|
|
||||||
double COORDINATOR_HOSTNAME_RESOLVE_DELAY;
|
|
||||||
double COORDINATOR_RECONNECTION_DELAY;
|
double COORDINATOR_RECONNECTION_DELAY;
|
||||||
int CLIENT_EXAMPLE_AMOUNT;
|
int CLIENT_EXAMPLE_AMOUNT;
|
||||||
double MAX_CLIENT_STATUS_AGE;
|
double MAX_CLIENT_STATUS_AGE;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "fdbclient/CommitProxyInterface.h"
|
#include "fdbclient/CommitProxyInterface.h"
|
||||||
#include "fdbclient/ClusterInterface.h"
|
#include "fdbclient/ClusterInterface.h"
|
||||||
#include "fdbclient/WellKnownEndpoints.h"
|
#include "fdbclient/WellKnownEndpoints.h"
|
||||||
|
#include "flow/Hostname.h"
|
||||||
|
|
||||||
const int MAX_CLUSTER_FILE_BYTES = 60000;
|
const int MAX_CLUSTER_FILE_BYTES = 60000;
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ ACTOR Future<Void> monitorNominee(Key key,
|
|||||||
.detail("OldAddr", coord.getLeader.getEndpoint().getPrimaryAddress().toString());
|
.detail("OldAddr", coord.getLeader.getEndpoint().getPrimaryAddress().toString());
|
||||||
if (rep.getError().code() == error_code_request_maybe_delivered) {
|
if (rep.getError().code() == error_code_request_maybe_delivered) {
|
||||||
// Delay to prevent tight resolving loop due to outdated DNS cache
|
// Delay to prevent tight resolving loop due to outdated DNS cache
|
||||||
wait(delay(CLIENT_KNOBS->COORDINATOR_HOSTNAME_RESOLVE_DELAY));
|
wait(delay(FLOW_KNOBS->HOSTNAME_RESOLVE_DELAY));
|
||||||
throw coordinators_changed();
|
throw coordinators_changed();
|
||||||
} else {
|
} else {
|
||||||
throw rep.getError();
|
throw rep.getError();
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <boost/algorithm/string/classification.hpp>
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include "fdbrpc/IAsyncFile.h"
|
#include "fdbrpc/IAsyncFile.h"
|
||||||
|
#include "flow/Hostname.h"
|
||||||
#include "flow/UnitTest.h"
|
#include "flow/UnitTest.h"
|
||||||
#include "fdbclient/rapidxml/rapidxml.hpp"
|
#include "fdbclient/rapidxml/rapidxml.hpp"
|
||||||
#include "fdbclient/FDBAWSCredentialsProvider.h"
|
#include "fdbclient/FDBAWSCredentialsProvider.h"
|
||||||
|
@ -51,7 +51,7 @@ ACTOR Future<Void> submitCandidacy(Key key,
|
|||||||
.detail("OldAddr", coord.candidacy.getEndpoint().getPrimaryAddress().toString());
|
.detail("OldAddr", coord.candidacy.getEndpoint().getPrimaryAddress().toString());
|
||||||
if (rep.getError().code() == error_code_request_maybe_delivered) {
|
if (rep.getError().code() == error_code_request_maybe_delivered) {
|
||||||
// Delay to prevent tight resolving loop due to outdated DNS cache
|
// Delay to prevent tight resolving loop due to outdated DNS cache
|
||||||
wait(delay(CLIENT_KNOBS->COORDINATOR_HOSTNAME_RESOLVE_DELAY));
|
wait(delay(FLOW_KNOBS->HOSTNAME_RESOLVE_DELAY));
|
||||||
throw coordinators_changed();
|
throw coordinators_changed();
|
||||||
} else {
|
} else {
|
||||||
throw rep.getError();
|
throw rep.getError();
|
||||||
|
@ -30,6 +30,8 @@ set(FLOW_SRCS
|
|||||||
Hash3.h
|
Hash3.h
|
||||||
Histogram.cpp
|
Histogram.cpp
|
||||||
Histogram.h
|
Histogram.h
|
||||||
|
Hostname.actor.cpp
|
||||||
|
Hostname.h
|
||||||
IDispatched.h
|
IDispatched.h
|
||||||
IRandom.h
|
IRandom.h
|
||||||
IThreadPoolTest.actor.cpp
|
IThreadPoolTest.actor.cpp
|
||||||
|
194
flow/Hostname.actor.cpp
Normal file
194
flow/Hostname.actor.cpp
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* Hostname.actor.cpp
|
||||||
|
*
|
||||||
|
* This source file is part of the FoundationDB open source project
|
||||||
|
*
|
||||||
|
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "flow/Hostname.h"
|
||||||
|
#include "flow/UnitTest.h"
|
||||||
|
#include "flow/actorcompiler.h" // has to be last include
|
||||||
|
|
||||||
|
Hostname Hostname::parse(const std::string& s) {
|
||||||
|
if (s.empty() || !Hostname::isHostname(s)) {
|
||||||
|
throw connection_string_invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTLS = false;
|
||||||
|
std::string f;
|
||||||
|
if (s.size() > 4 && strcmp(s.c_str() + s.size() - 4, ":tls") == 0) {
|
||||||
|
isTLS = true;
|
||||||
|
f = s.substr(0, s.size() - 4);
|
||||||
|
} else {
|
||||||
|
f = s;
|
||||||
|
}
|
||||||
|
auto colonPos = f.find_first_of(":");
|
||||||
|
return Hostname(f.substr(0, colonPos), f.substr(colonPos + 1), isTLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hostname::resetToUnresolved() {
|
||||||
|
if (status == Hostname::RESOLVED) {
|
||||||
|
status = UNRESOLVED;
|
||||||
|
resolvedAddress = Optional<NetworkAddress>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTOR Future<Void> resolveImpl(Hostname* self) {
|
||||||
|
loop {
|
||||||
|
if (self->status == Hostname::UNRESOLVED) {
|
||||||
|
self->status = Hostname::RESOLVING;
|
||||||
|
try {
|
||||||
|
std::vector<NetworkAddress> addresses =
|
||||||
|
wait(INetworkConnections::net()->resolveTCPEndpointWithDNSCache(self->host, self->service));
|
||||||
|
NetworkAddress address = addresses[deterministicRandom()->randomInt(0, addresses.size())];
|
||||||
|
address.flags = 0; // Reset the parsed address to public
|
||||||
|
address.fromHostname = NetworkAddressFromHostname::True;
|
||||||
|
if (self->isTLS) {
|
||||||
|
address.flags |= NetworkAddress::FLAG_TLS;
|
||||||
|
}
|
||||||
|
self->resolvedAddress = address;
|
||||||
|
self->status = Hostname::RESOLVED;
|
||||||
|
break;
|
||||||
|
} catch (...) {
|
||||||
|
self->status = Hostname::UNRESOLVED;
|
||||||
|
self->resolveFinish.trigger();
|
||||||
|
self->resolvedAddress = Optional<NetworkAddress>();
|
||||||
|
wait(delay(FLOW_KNOBS->HOSTNAME_RESOLVE_DELAY));
|
||||||
|
}
|
||||||
|
} else if (self->status == Hostname::RESOLVING) {
|
||||||
|
wait(self->resolveFinish.onTrigger());
|
||||||
|
if (self->status == Hostname::RESOLVED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Otherwise, this means other threads failed on resolve, so here we go back to the loop and try to resolve
|
||||||
|
// again.
|
||||||
|
} else {
|
||||||
|
// status is RESOLVED, nothing to do.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Void> Hostname::resolve() {
|
||||||
|
return resolveImpl(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hostname::resolveBlocking() {
|
||||||
|
if (status != RESOLVED) {
|
||||||
|
try {
|
||||||
|
std::vector<NetworkAddress> addresses =
|
||||||
|
INetworkConnections::net()->resolveTCPEndpointBlockingWithDNSCache(host, service);
|
||||||
|
NetworkAddress address = addresses[deterministicRandom()->randomInt(0, addresses.size())];
|
||||||
|
address.flags = 0; // Reset the parsed address to public
|
||||||
|
address.fromHostname = NetworkAddressFromHostname::True;
|
||||||
|
if (isTLS) {
|
||||||
|
address.flags |= NetworkAddress::FLAG_TLS;
|
||||||
|
}
|
||||||
|
resolvedAddress = address;
|
||||||
|
status = RESOLVED;
|
||||||
|
} catch (...) {
|
||||||
|
status = UNRESOLVED;
|
||||||
|
resolvedAddress = Optional<NetworkAddress>();
|
||||||
|
throw lookup_failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("/flow/Hostname/hostname") {
|
||||||
|
std::string hn1s = "localhost:1234";
|
||||||
|
std::string hn2s = "host-name:1234";
|
||||||
|
std::string hn3s = "host.name:1234";
|
||||||
|
std::string hn4s = "host-name_part1.host-name_part2:1234:tls";
|
||||||
|
|
||||||
|
std::string hn5s = "127.0.0.1:1234";
|
||||||
|
std::string hn6s = "127.0.0.1:1234:tls";
|
||||||
|
std::string hn7s = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4800";
|
||||||
|
std::string hn8s = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4800:tls";
|
||||||
|
std::string hn9s = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
|
||||||
|
std::string hn10s = "2001:0db8:85a3:0000:0000:8a2e:0370:7334:tls";
|
||||||
|
std::string hn11s = "[::1]:4800";
|
||||||
|
std::string hn12s = "[::1]:4800:tls";
|
||||||
|
std::string hn13s = "1234";
|
||||||
|
|
||||||
|
auto hn1 = Hostname::parse(hn1s);
|
||||||
|
ASSERT(hn1.toString() == hn1s);
|
||||||
|
ASSERT(hn1.host == "localhost");
|
||||||
|
ASSERT(hn1.service == "1234");
|
||||||
|
ASSERT(!hn1.isTLS);
|
||||||
|
|
||||||
|
state Hostname hn2 = Hostname::parse(hn2s);
|
||||||
|
ASSERT(hn2.toString() == hn2s);
|
||||||
|
ASSERT(hn2.host == "host-name");
|
||||||
|
ASSERT(hn2.service == "1234");
|
||||||
|
ASSERT(!hn2.isTLS);
|
||||||
|
|
||||||
|
auto hn3 = Hostname::parse(hn3s);
|
||||||
|
ASSERT(hn3.toString() == hn3s);
|
||||||
|
ASSERT(hn3.host == "host.name");
|
||||||
|
ASSERT(hn3.service == "1234");
|
||||||
|
ASSERT(!hn3.isTLS);
|
||||||
|
|
||||||
|
auto hn4 = Hostname::parse(hn4s);
|
||||||
|
ASSERT(hn4.toString() == hn4s);
|
||||||
|
ASSERT(hn4.host == "host-name_part1.host-name_part2");
|
||||||
|
ASSERT(hn4.service == "1234");
|
||||||
|
ASSERT(hn4.isTLS);
|
||||||
|
|
||||||
|
ASSERT(!Hostname::isHostname(hn5s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn6s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn7s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn8s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn9s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn10s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn11s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn12s));
|
||||||
|
ASSERT(!Hostname::isHostname(hn13s));
|
||||||
|
|
||||||
|
ASSERT(hn1.status == Hostname::UNRESOLVED && !hn1.resolvedAddress.present());
|
||||||
|
ASSERT(hn2.status == Hostname::UNRESOLVED && !hn2.resolvedAddress.present());
|
||||||
|
ASSERT(hn3.status == Hostname::UNRESOLVED && !hn3.resolvedAddress.present());
|
||||||
|
ASSERT(hn4.status == Hostname::UNRESOLVED && !hn4.resolvedAddress.present());
|
||||||
|
|
||||||
|
try {
|
||||||
|
wait(timeoutError(hn2.resolve(), 1));
|
||||||
|
} catch (Error& e) {
|
||||||
|
ASSERT(e.code() == error_code_timed_out);
|
||||||
|
}
|
||||||
|
ASSERT(hn2.status == Hostname::UNRESOLVED && !hn2.resolvedAddress.present());
|
||||||
|
|
||||||
|
try {
|
||||||
|
hn2.resolveBlocking();
|
||||||
|
} catch (Error& e) {
|
||||||
|
ASSERT(e.code() == error_code_lookup_failed);
|
||||||
|
}
|
||||||
|
ASSERT(hn2.status == Hostname::UNRESOLVED && !hn2.resolvedAddress.present());
|
||||||
|
|
||||||
|
state NetworkAddress address = NetworkAddress::parse("127.0.0.0:1234");
|
||||||
|
INetworkConnections::net()->addMockTCPEndpoint("host-name", "1234", { address });
|
||||||
|
wait(hn2.resolve());
|
||||||
|
ASSERT(hn2.status == Hostname::RESOLVED);
|
||||||
|
ASSERT(hn2.resolvedAddress.present() && hn2.resolvedAddress.get() == address);
|
||||||
|
|
||||||
|
hn2.resetToUnresolved();
|
||||||
|
ASSERT(hn2.status == Hostname::UNRESOLVED && !hn2.resolvedAddress.present());
|
||||||
|
|
||||||
|
hn2.resolveBlocking();
|
||||||
|
ASSERT(hn2.status == Hostname::RESOLVED);
|
||||||
|
ASSERT(hn2.resolvedAddress.present() && hn2.resolvedAddress.get() == address);
|
||||||
|
|
||||||
|
return Void();
|
||||||
|
}
|
85
flow/Hostname.h
Normal file
85
flow/Hostname.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Hostname.h
|
||||||
|
*
|
||||||
|
* This source file is part of the FoundationDB open source project
|
||||||
|
*
|
||||||
|
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLOW_HOSTNAME_H
|
||||||
|
#define FLOW_HOSTNAME_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "flow/network.h"
|
||||||
|
#include "flow/genericactors.actor.h"
|
||||||
|
|
||||||
|
struct Hostname {
|
||||||
|
std::string host;
|
||||||
|
std::string service; // decimal port number
|
||||||
|
bool isTLS;
|
||||||
|
|
||||||
|
Hostname(const std::string& host, const std::string& service, bool isTLS)
|
||||||
|
: host(host), service(service), isTLS(isTLS) {}
|
||||||
|
Hostname() : host(""), service(""), isTLS(false) {}
|
||||||
|
Hostname(const Hostname& rhs) { operator=(rhs); }
|
||||||
|
Hostname& operator=(const Hostname& rhs) {
|
||||||
|
// Copy everything except AsyncTrigger resolveFinish.
|
||||||
|
host = rhs.host;
|
||||||
|
service = rhs.service;
|
||||||
|
isTLS = rhs.isTLS;
|
||||||
|
resolvedAddress = rhs.resolvedAddress;
|
||||||
|
status = rhs.status;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Hostname& r) const { return host == r.host && service == r.service && isTLS == r.isTLS; }
|
||||||
|
bool operator!=(const Hostname& r) const { return !(*this == r); }
|
||||||
|
bool operator<(const Hostname& r) const {
|
||||||
|
if (isTLS != r.isTLS)
|
||||||
|
return isTLS < r.isTLS;
|
||||||
|
else if (host != r.host)
|
||||||
|
return host < r.host;
|
||||||
|
return service < r.service;
|
||||||
|
}
|
||||||
|
bool operator>(const Hostname& r) const { return r < *this; }
|
||||||
|
bool operator<=(const Hostname& r) const { return !(*this > r); }
|
||||||
|
bool operator>=(const Hostname& r) const { return !(*this < r); }
|
||||||
|
|
||||||
|
// Allow hostnames in forms like following:
|
||||||
|
// hostname:1234
|
||||||
|
// host.name:1234
|
||||||
|
// host-name:1234
|
||||||
|
// host-name_part1.host-name_part2:1234:tls
|
||||||
|
static bool isHostname(const std::string& s) {
|
||||||
|
std::regex validation("^([\\w\\-]+\\.?)+:([\\d]+){1,}(:tls)?$");
|
||||||
|
std::regex ipv4Validation("^([\\d]{1,3}\\.?){4,}:([\\d]+){1,}(:tls)?$");
|
||||||
|
return !std::regex_match(s, ipv4Validation) && std::regex_match(s, validation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Hostname parse(const std::string& s);
|
||||||
|
|
||||||
|
std::string toString() const { return host + ":" + service + (isTLS ? ":tls" : ""); }
|
||||||
|
|
||||||
|
Optional<NetworkAddress> resolvedAddress;
|
||||||
|
enum HostnameStatus { UNRESOLVED, RESOLVING, RESOLVED };
|
||||||
|
Future<Void> resolve();
|
||||||
|
void resolveBlocking(); // This one should only be used when resolving asynchronously is impossible.
|
||||||
|
// For all other cases, resolve() should be preferred.
|
||||||
|
void resetToUnresolved();
|
||||||
|
HostnameStatus status = UNRESOLVED;
|
||||||
|
AsyncTrigger resolveFinish;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -40,6 +40,7 @@ FlowKnobs const* FLOW_KNOBS = &bootstrapGlobalFlowKnobs;
|
|||||||
void FlowKnobs::initialize(Randomize randomize, IsSimulated isSimulated) {
|
void FlowKnobs::initialize(Randomize randomize, IsSimulated isSimulated) {
|
||||||
init( AUTOMATIC_TRACE_DUMP, 1 );
|
init( AUTOMATIC_TRACE_DUMP, 1 );
|
||||||
init( PREVENT_FAST_SPIN_DELAY, .01 );
|
init( PREVENT_FAST_SPIN_DELAY, .01 );
|
||||||
|
init( HOSTNAME_RESOLVE_DELAY, .05 );
|
||||||
init( CACHE_REFRESH_INTERVAL_WHEN_ALL_ALTERNATIVES_FAILED, 1.0 );
|
init( CACHE_REFRESH_INTERVAL_WHEN_ALL_ALTERNATIVES_FAILED, 1.0 );
|
||||||
|
|
||||||
init( DELAY_JITTER_OFFSET, 0.9 );
|
init( DELAY_JITTER_OFFSET, 0.9 );
|
||||||
|
@ -113,6 +113,7 @@ class FlowKnobs : public KnobsImpl<FlowKnobs> {
|
|||||||
public:
|
public:
|
||||||
int AUTOMATIC_TRACE_DUMP;
|
int AUTOMATIC_TRACE_DUMP;
|
||||||
double PREVENT_FAST_SPIN_DELAY;
|
double PREVENT_FAST_SPIN_DELAY;
|
||||||
|
double HOSTNAME_RESOLVE_DELAY;
|
||||||
double CACHE_REFRESH_INTERVAL_WHEN_ALL_ALTERNATIVES_FAILED;
|
double CACHE_REFRESH_INTERVAL_WHEN_ALL_ALTERNATIVES_FAILED;
|
||||||
|
|
||||||
double DELAY_JITTER_OFFSET;
|
double DELAY_JITTER_OFFSET;
|
||||||
|
@ -63,23 +63,6 @@ bool IPAddress::isValid() const {
|
|||||||
return std::get<uint32_t>(addr) != 0;
|
return std::get<uint32_t>(addr) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hostname Hostname::parse(const std::string& s) {
|
|
||||||
if (s.empty()) {
|
|
||||||
throw connection_string_invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTLS = false;
|
|
||||||
std::string f;
|
|
||||||
if (s.size() > 4 && strcmp(s.c_str() + s.size() - 4, ":tls") == 0) {
|
|
||||||
isTLS = true;
|
|
||||||
f = s.substr(0, s.size() - 4);
|
|
||||||
} else {
|
|
||||||
f = s;
|
|
||||||
}
|
|
||||||
auto colonPos = f.find_first_of(":");
|
|
||||||
return Hostname(f.substr(0, colonPos), f.substr(colonPos + 1), isTLS);
|
|
||||||
}
|
|
||||||
|
|
||||||
FDB_DEFINE_BOOLEAN_PARAM(NetworkAddressFromHostname);
|
FDB_DEFINE_BOOLEAN_PARAM(NetworkAddressFromHostname);
|
||||||
|
|
||||||
NetworkAddress NetworkAddress::parse(std::string const& s) {
|
NetworkAddress NetworkAddress::parse(std::string const& s) {
|
||||||
@ -220,7 +203,7 @@ std::string DNSCache::toString() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DNSCache DNSCache::parseFromString(const std::string& s) {
|
DNSCache DNSCache::parseFromString(const std::string& s) {
|
||||||
std::unordered_map<std::string, std::vector<NetworkAddress>> dnsCache;
|
std::map<std::string, std::vector<NetworkAddress>> dnsCache;
|
||||||
|
|
||||||
for (int p = 0; p < s.length();) {
|
for (int p = 0; p < s.length();) {
|
||||||
int pSemiColumn = s.find_first_of(';', p);
|
int pSemiColumn = s.find_first_of(';', p);
|
||||||
@ -364,62 +347,4 @@ TEST_CASE("/flow/network/ipaddress") {
|
|||||||
return Void();
|
return Void();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("/flow/network/hostname") {
|
|
||||||
std::string hn1s = "localhost:1234";
|
|
||||||
std::string hn2s = "host-name:1234";
|
|
||||||
std::string hn3s = "host.name:1234";
|
|
||||||
std::string hn4s = "host-name_part1.host-name_part2:1234:tls";
|
|
||||||
|
|
||||||
std::string hn5s = "127.0.0.1:1234";
|
|
||||||
std::string hn6s = "127.0.0.1:1234:tls";
|
|
||||||
std::string hn7s = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4800";
|
|
||||||
std::string hn8s = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4800:tls";
|
|
||||||
std::string hn9s = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
|
|
||||||
std::string hn10s = "2001:0db8:85a3:0000:0000:8a2e:0370:7334:tls";
|
|
||||||
std::string hn11s = "[::1]:4800";
|
|
||||||
std::string hn12s = "[::1]:4800:tls";
|
|
||||||
std::string hn13s = "1234";
|
|
||||||
|
|
||||||
auto hn1 = Hostname::parse(hn1s);
|
|
||||||
ASSERT(hn1.toString() == hn1s);
|
|
||||||
ASSERT(hn1.host == "localhost");
|
|
||||||
ASSERT(hn1.service == "1234");
|
|
||||||
ASSERT(!hn1.isTLS);
|
|
||||||
|
|
||||||
auto hn2 = Hostname::parse(hn2s);
|
|
||||||
ASSERT(hn2.toString() == hn2s);
|
|
||||||
ASSERT(hn2.host == "host-name");
|
|
||||||
ASSERT(hn2.service == "1234");
|
|
||||||
ASSERT(!hn2.isTLS);
|
|
||||||
|
|
||||||
auto hn3 = Hostname::parse(hn3s);
|
|
||||||
ASSERT(hn3.toString() == hn3s);
|
|
||||||
ASSERT(hn3.host == "host.name");
|
|
||||||
ASSERT(hn3.service == "1234");
|
|
||||||
ASSERT(!hn3.isTLS);
|
|
||||||
|
|
||||||
auto hn4 = Hostname::parse(hn4s);
|
|
||||||
ASSERT(hn4.toString() == hn4s);
|
|
||||||
ASSERT(hn4.host == "host-name_part1.host-name_part2");
|
|
||||||
ASSERT(hn4.service == "1234");
|
|
||||||
ASSERT(hn4.isTLS);
|
|
||||||
|
|
||||||
ASSERT(Hostname::isHostname(hn1s));
|
|
||||||
ASSERT(Hostname::isHostname(hn2s));
|
|
||||||
ASSERT(Hostname::isHostname(hn3s));
|
|
||||||
ASSERT(Hostname::isHostname(hn4s));
|
|
||||||
|
|
||||||
ASSERT(!Hostname::isHostname(hn5s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn6s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn7s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn8s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn9s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn10s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn11s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn12s));
|
|
||||||
ASSERT(!Hostname::isHostname(hn13s));
|
|
||||||
|
|
||||||
return Void();
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkInfo::NetworkInfo() : handshakeLock(new FlowLock(FLOW_KNOBS->TLS_HANDSHAKE_LIMIT)) {}
|
NetworkInfo::NetworkInfo() : handshakeLock(new FlowLock(FLOW_KNOBS->TLS_HANDSHAKE_LIMIT)) {}
|
||||||
|
@ -135,43 +135,6 @@ inline TaskPriority incrementPriorityIfEven(TaskPriority p) {
|
|||||||
|
|
||||||
class Void;
|
class Void;
|
||||||
|
|
||||||
struct Hostname {
|
|
||||||
std::string host;
|
|
||||||
std::string service; // decimal port number
|
|
||||||
bool isTLS;
|
|
||||||
|
|
||||||
Hostname(std::string host, std::string service, bool isTLS) : host(host), service(service), isTLS(isTLS) {}
|
|
||||||
Hostname() : host(""), service(""), isTLS(false) {}
|
|
||||||
|
|
||||||
bool operator==(const Hostname& r) const { return host == r.host && service == r.service && isTLS == r.isTLS; }
|
|
||||||
bool operator!=(const Hostname& r) const { return !(*this == r); }
|
|
||||||
bool operator<(const Hostname& r) const {
|
|
||||||
if (isTLS != r.isTLS)
|
|
||||||
return isTLS < r.isTLS;
|
|
||||||
else if (host != r.host)
|
|
||||||
return host < r.host;
|
|
||||||
return service < r.service;
|
|
||||||
}
|
|
||||||
bool operator>(const Hostname& r) const { return r < *this; }
|
|
||||||
bool operator<=(const Hostname& r) const { return !(*this > r); }
|
|
||||||
bool operator>=(const Hostname& r) const { return !(*this < r); }
|
|
||||||
|
|
||||||
// Allow hostnames in forms like following:
|
|
||||||
// hostname:1234
|
|
||||||
// host.name:1234
|
|
||||||
// host-name:1234
|
|
||||||
// host-name_part1.host-name_part2:1234:tls
|
|
||||||
static bool isHostname(const std::string& s) {
|
|
||||||
std::regex validation("^([\\w\\-]+\\.?)+:([\\d]+){1,}(:tls)?$");
|
|
||||||
std::regex ipv4Validation("^([\\d]{1,3}\\.?){4,}:([\\d]+){1,}(:tls)?$");
|
|
||||||
return !std::regex_match(s, ipv4Validation) && std::regex_match(s, validation);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hostname parse(const std::string& s);
|
|
||||||
|
|
||||||
std::string toString() const { return host + ":" + service + (isTLS ? ":tls" : ""); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IPAddress {
|
struct IPAddress {
|
||||||
typedef boost::asio::ip::address_v6::bytes_type IPAddressStore;
|
typedef boost::asio::ip::address_v6::bytes_type IPAddressStore;
|
||||||
static_assert(std::is_same<IPAddressStore, std::array<uint8_t, 16>>::value,
|
static_assert(std::is_same<IPAddressStore, std::array<uint8_t, 16>>::value,
|
||||||
@ -701,7 +664,7 @@ public:
|
|||||||
class DNSCache {
|
class DNSCache {
|
||||||
public:
|
public:
|
||||||
DNSCache() = default;
|
DNSCache() = default;
|
||||||
explicit DNSCache(const std::unordered_map<std::string, std::vector<NetworkAddress>>& dnsCache)
|
explicit DNSCache(const std::map<std::string, std::vector<NetworkAddress>>& dnsCache)
|
||||||
: hostnameToAddresses(dnsCache) {}
|
: hostnameToAddresses(dnsCache) {}
|
||||||
|
|
||||||
Optional<std::vector<NetworkAddress>> find(const std::string& host, const std::string& service);
|
Optional<std::vector<NetworkAddress>> find(const std::string& host, const std::string& service);
|
||||||
@ -715,7 +678,7 @@ public:
|
|||||||
static DNSCache parseFromString(const std::string& s);
|
static DNSCache parseFromString(const std::string& s);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::vector<NetworkAddress>> hostnameToAddresses;
|
std::map<std::string, std::vector<NetworkAddress>> hostnameToAddresses;
|
||||||
};
|
};
|
||||||
|
|
||||||
class INetworkConnections {
|
class INetworkConnections {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user