Skip to content

Commit

Permalink
Add ability to specify DNS seeds
Browse files Browse the repository at this point in the history
It's currently part of a separate config field to
cleanly separate between Agora nodes and DNS seeds.

It may later be merged into a common section if necessary.
  • Loading branch information
AndrejMitrovic committed Jun 20, 2019
1 parent 4477cb4 commit 80bc15e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 5 deletions.
3 changes: 3 additions & 0 deletions doc/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ network:
# Supported value: IPv4, IPv6
- http://192.168.1.42:2828
- http://192.168.0.44:2828
seed:
# Supported value: FQDN seed
- seed.bosagora.io

################################################################################
## Quorum slices ##
Expand Down
27 changes: 22 additions & 5 deletions source/agora/common/Config.d
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public void verifyConfigFile ( Config config )
getAllValidators(config.quorums, all_validators);
enforce(config.node.key_pair.address !in all_validators,
format("Cannot have our own key as a validator node: %s", config.node.key_pair.address));

enforce(config.network.length > 0 || config.seed.length > 0,
"Config file must specify the seed IPs or seed nodes");
}

// extract the set of all validators as configured in the quorum config
Expand Down Expand Up @@ -79,6 +82,9 @@ public struct Config
/// The list of IPs for use with network discovery
public immutable Address[] network;

/// The list of FQDN seeds for use with network discovery
public immutable string[] seed;

/// The quorum slice config
public immutable QuorumConfig[] quorums;

Expand Down Expand Up @@ -172,20 +178,31 @@ public Config parseConfigFile (CommandLine cmdln)

Node root = Loader.fromFile(cmdln.config_path).load();

enforce("network" in root && root["network"].isSequence,
"The 'network' section is mandatory and must specify at least one peer");
string[] parseSequence ( string name )
{
string[] result;

Address[] network;
foreach (string address; root["network"])
network ~= Address.fromString(address);
if (auto sequence = name in root)
{
enforce(sequence.isSequence, format("%s config section must be a sequence", name));
foreach (string address; *sequence)
result ~= address;
}

return result;
}

Address[] network = parseSequence("network")
.map!(a => Address.fromString(a)).array;
string[] seed = parseSequence("seed");
enforce("node" in root, "The 'node' section is required");
enforce("quorum" in root, "The 'quorum' section is required");

Config conf =
{
node : parseNodeConfig(root["node"]),
network : assumeUnique(network),
seed : assumeUnique(seed),
quorums : assumeUnique(parseQuorumSection(root["quorum"]))
};

Expand Down
57 changes: 57 additions & 0 deletions source/agora/node/Network.d
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class Network
{
logInfo("Discovering from %s", this.config.network);
this.addAddresses(Set!Address.from(this.config.network));
logInfo("Resolving DNS from %s", this.config.seed);
this.addAddresses(resolveDnsSeeds(this.config.seed));

while (!this.allQuorumNodesFound())
{
Expand Down Expand Up @@ -241,3 +243,58 @@ class Network
this.known_addresses);
}
}

/*******************************************************************************
Resolves IPs out of a list of DNS seeds
Params:
addresses = the set of DNS seeds
Returns:
The resolved set of IPs
*******************************************************************************/

private Set!Address resolveDnsSeeds ( in string[] seed )
{
import std.conv;
import std.string;
import std.socket : getAddressInfo, AddressFamily, ProtocolType;

Set!Address resolved_ips;

foreach (host; seed)
try
{
logInfo("DNS: contacting seed '%s'..", host);
foreach (addr_info; getAddressInfo(host))
{
logTrace("DNS: checking address %s", addr_info);
if (addr_info.family != AddressFamily.INET &&
addr_info.family != AddressFamily.INET6)
{
logTrace("DNS: rejected non-IP family %s", addr_info.family);
continue;
}

// we only support TCP for now
if (addr_info.protocol != ProtocolType.TCP)
{
logTrace("DNS: rejected non-TCP node %s", addr_info);
continue;
}

// if the port is set to zero, assume default Boa port
auto ip = addr_info.address.to!string.replace(":0", ":2826");
logInfo("DNS: accepted IP %s", ip);
resolved_ips.put(Address.fromString(ip));
}
}
catch (Exception ex)
{
logError("Error: %s", ex);
}

return resolved_ips;
}

0 comments on commit 80bc15e

Please sign in to comment.