|
@@ -6,6 +6,7 @@ namespace Riddle {
|
|
|
|
|
|
public const int REGISTRATION_TIMEOUT_US = 600000000;
|
|
|
public const int GOSSIP_INTERVAL_US = 2000000;
|
|
|
+ public const int SYNC_INTERVAL_US = 2000000;
|
|
|
public const string RIDDLE_SERVER_GROUP = "Riddle";
|
|
|
|
|
|
private SocketService service;
|
|
@@ -15,12 +16,13 @@ namespace Riddle {
|
|
|
private Client client;
|
|
|
|
|
|
private Fifo<Gossip> gossip = new Fifo<Gossip>();
|
|
|
+ private Fifo<InetSocketAddress> sync_queue = new Fifo<InetSocketAddress>();
|
|
|
private Gee.HashSet<string> gossip_idempotency_tokens = new Gee.HashSet<string>();
|
|
|
- private Thread<bool> gossip_thread;
|
|
|
private uint16 port;
|
|
|
|
|
|
|
|
|
public Server(string address, uint16 port, NameInfoStore name_store) throws Error {
|
|
|
+ name_store.clean();
|
|
|
this.names = name_store;
|
|
|
this.port = port;
|
|
|
var add = new InetAddress.from_string(address);
|
|
@@ -29,7 +31,8 @@ namespace Riddle {
|
|
|
|
|
|
client = new Client.with_server(new InetSocketAddress(add, port));
|
|
|
client.join(RIDDLE_SERVER_GROUP, port);
|
|
|
- gossip_thread = new Thread<bool>("Gossip", spread_gossip);
|
|
|
+ new Thread<bool>("Gossip", spread_gossip);
|
|
|
+ new Thread<bool>("NameSync", server_sync);
|
|
|
}
|
|
|
|
|
|
public async void start() {
|
|
@@ -77,6 +80,21 @@ namespace Riddle {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ private bool server_sync() {
|
|
|
+ foreach (var server in sync_queue) {
|
|
|
+ try {
|
|
|
+ lock(names) {
|
|
|
+ client.sync(server, names);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch(Error e) {
|
|
|
+ warning(@"Error while attempting to auto-sync with server: $(e.message)");
|
|
|
+ }
|
|
|
+ Thread.usleep(SYNC_INTERVAL_US);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
private Message service_message(Message msg, InetSocketAddress origin) throws Error {
|
|
|
|
|
|
switch (msg.message_type) {
|
|
@@ -94,6 +112,8 @@ namespace Riddle {
|
|
|
return handle_riddle(msg, origin);
|
|
|
case MessageType.CALLBACK:
|
|
|
return handle_callback(msg);
|
|
|
+ case MessageType.SYNC:
|
|
|
+ return handle_sync(msg);
|
|
|
default:
|
|
|
return new Message(MessageType.ERROR, new string[] { "unknown-command" }, new string[0]);
|
|
|
}
|
|
@@ -221,6 +241,19 @@ namespace Riddle {
|
|
|
return new Message(MessageType.ERROR, new string[] { "not-implemented" }, new string[0]);
|
|
|
}
|
|
|
|
|
|
+ private Message handle_sync(Message msg) throws Error {
|
|
|
+ var query = names.get_all();
|
|
|
+ foreach (var existing in msg.items) {
|
|
|
+ var parts = existing.split(" ", 2);
|
|
|
+ var name = parts[0];
|
|
|
+ var effective_date = new DateTime.from_iso8601(parts[1], null);
|
|
|
+
|
|
|
+ query = query.where(info => info.name != name || info.effective.difference(effective_date) > 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Message(MessageType.DOMAINS, new string[0], query.select<string>(i => @"$(i.name) $(i.get_encoded())").to_array());
|
|
|
+ }
|
|
|
+
|
|
|
private void cleanup_registrations() {
|
|
|
lock(registrations) {
|
|
|
var copy = new Gee.HashMap<string, Invercargill.Sequence<Registration>>();
|
|
@@ -245,6 +278,10 @@ namespace Riddle {
|
|
|
|
|
|
registrations[group].add(reg);
|
|
|
}
|
|
|
+
|
|
|
+ if(group == RIDDLE_SERVER_GROUP) {
|
|
|
+ sync_queue.push(address);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void remove_registration(string group, InetSocketAddress address) {
|