|
@@ -6,9 +6,14 @@ namespace Riddle {
|
|
|
|
|
|
private Invercargill.Sequence<PeerDiscoverer> discoverers = new Invercargill.Sequence<PeerDiscoverer> ();
|
|
|
private Invercargill.Sequence<InetSocketAddress> servers = new Invercargill.Sequence<InetSocketAddress>();
|
|
|
+ private Invercargill.Sequence<InetSocketAddress> local_servers = new Invercargill.Sequence<InetSocketAddress>();
|
|
|
private Invercargill.Sequence<Message> join_messages = new Invercargill.Sequence<Message>();
|
|
|
private InetSocketAddress? self_server = null;
|
|
|
|
|
|
+ public Invercargill.Enumerable<InetSocketAddress> discovered_servers { get {
|
|
|
+ return servers;
|
|
|
+ }}
|
|
|
+
|
|
|
public Client() {
|
|
|
discoverers.add (new KnownHostDiscoverer());
|
|
|
discoverers.add (new LanDiscoverer());
|
|
@@ -26,19 +31,44 @@ namespace Riddle {
|
|
|
lan_discoverer.advertise(self_server);
|
|
|
}
|
|
|
|
|
|
+ public Client.with_dbus(DBusService service) throws Error {
|
|
|
+ discoverers.add (new KnownHostDiscoverer());
|
|
|
+ discoverers.add (new LanDiscoverer());
|
|
|
+
|
|
|
+ // Add server associated with dbus server as local peer
|
|
|
+ new_server_found(new InetSocketAddress(new InetAddress.from_string(service.local_server_address()), service.local_server_port()), true);
|
|
|
+
|
|
|
+ // Add any servers our server knows about
|
|
|
+ var peers = service.discovered_servers();
|
|
|
+ foreach (var peer in peers) {
|
|
|
+ var parts = peer.split(" ");
|
|
|
+ var address = new InetSocketAddress(new InetAddress.from_string(parts[0]), (uint16)int.parse(parts[1]));
|
|
|
+ new_server_found(address, service.is_peer_local(parts[0]));
|
|
|
+ }
|
|
|
+ setup();
|
|
|
+ }
|
|
|
+
|
|
|
private void setup() {
|
|
|
foreach (var discoverer in discoverers) {
|
|
|
- discoverer.peer_discovered.connect(new_server_found);
|
|
|
+ discoverer.peer_discovered.connect(s => new_server_found(s, discoverer is LanDiscoverer));
|
|
|
discoverer.begin();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void new_server_found(InetSocketAddress address) {
|
|
|
+ private void new_server_found(InetSocketAddress address, bool is_lan) {
|
|
|
if(self_server != null && server_equals(address, self_server)) {
|
|
|
// Ignore self_server address
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ if(is_lan) {
|
|
|
+ if(local_servers.any(s => server_equals(s, address))) {
|
|
|
+ // Ignore already discovered server
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ local_servers.add(address);
|
|
|
+ }
|
|
|
+
|
|
|
if(servers.any(s => server_equals(s, address))) {
|
|
|
// Ignore already discovered server
|
|
|
return;
|
|
@@ -55,6 +85,15 @@ namespace Riddle {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public bool is_peer_local(InetAddress address) {
|
|
|
+ var string_address = address.to_string();
|
|
|
+ print(@"Is peer local? $string_address\n");
|
|
|
+ if(self_server != null && self_server.address.to_string() == string_address) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return local_servers.any(s => s.address.to_string() == string_address);
|
|
|
+ }
|
|
|
+
|
|
|
public int join(string group, uint port) {
|
|
|
lock(join_messages) {
|
|
|
var msg = new Message(MessageType.JOIN, new string[] { group, port.to_string() }, new string[0]);
|
|
@@ -110,11 +149,14 @@ namespace Riddle {
|
|
|
}
|
|
|
|
|
|
public InetSocketAddress? callback(SolutionEnvelope solution, InetSocketAddress server, uint8[] author_signing_key, uint8[] reply_public_key, uint8[] reply_secret_key) throws Error {
|
|
|
+ print(@"[Client] Connecting to peer $(server)\n");
|
|
|
var socket = new SocketClient().connect(server);
|
|
|
var dis = new DataInputStream(socket.input_stream);
|
|
|
var dos = new DataOutputStream(socket.output_stream);
|
|
|
|
|
|
+ print("[Client] Sending message\n");
|
|
|
solution.to_message().send(dos);
|
|
|
+ print("[Client] Waiting for response\n");
|
|
|
var reply = Message.from_stream(dis);
|
|
|
|
|
|
if(reply.message_type == MessageType.NOT_ACCEPTED) {
|
|
@@ -122,11 +164,15 @@ namespace Riddle {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ print("[Client] Verifying response\n");
|
|
|
+
|
|
|
var verified_reply = Solution.verify_solved_response(reply, author_signing_key);
|
|
|
if(verified_reply == null) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ print("[Client] Decrypting response\n");
|
|
|
+
|
|
|
return Solution.decrypt_connection_details(verified_reply, reply_public_key, reply_secret_key);
|
|
|
|
|
|
}
|