|
@@ -1,7 +1,74 @@
|
|
|
+#include <iostream>
|
|
|
+
|
|
|
#include "config.hpp"
|
|
|
#include "net.hpp"
|
|
|
|
|
|
NetIO::NetIO(boost::asio::io_context &io_context, const Config &config)
|
|
|
- : conf(config)
|
|
|
+ : conf(config), myconf(config.nodes[config.my_node_num])
|
|
|
{
|
|
|
+ num_nodes = conf.nodes.size();
|
|
|
+ nodesockets.resize(num_nodes);
|
|
|
+ me = conf.my_node_num;
|
|
|
+
|
|
|
+ // Node number n will accept connections from nodes 0, ..., n-1 and
|
|
|
+ // make connections to nodes n+1, ..., num_nodes-1. This is all
|
|
|
+ // single threaded, but it doesn't deadlock because node 0 isn't
|
|
|
+ // waiting for any incoming connections, so it immediately makes
|
|
|
+ // outgoing connections. When it connects to node 1, that node
|
|
|
+ // accepts its (only) incoming connection, and then starts making
|
|
|
+ // its outgoing connections, etc.
|
|
|
+
|
|
|
+ tcp::resolver resolver(io_context);
|
|
|
+ tcp::acceptor acceptor(io_context,
|
|
|
+ resolver.resolve(myconf.listenhost, myconf.listenport)->endpoint());
|
|
|
+
|
|
|
+ for(size_t i=0; i<me; ++i) {
|
|
|
+#ifdef VERBOSE_NET
|
|
|
+ std::cerr << "Accepting number " << i << "\n";
|
|
|
+#endif
|
|
|
+ tcp::socket nodesock = acceptor.accept();
|
|
|
+#ifdef VERBOSE_NET
|
|
|
+ std::cerr << "Accepted number " << i << "\n";
|
|
|
+#endif
|
|
|
+ // Read 2 bytes from the socket, which will be the
|
|
|
+ // connecting node's node number
|
|
|
+ unsigned short node_num;
|
|
|
+ boost::asio::read(nodesock,
|
|
|
+ boost::asio::buffer(&node_num, sizeof(node_num)));
|
|
|
+ if (node_num >= num_nodes) {
|
|
|
+ std::cerr << "Received bad node number\n";
|
|
|
+ } else {
|
|
|
+ nodesockets[node_num] = std::move(nodesock);
|
|
|
+#ifdef VERBOSE_NET
|
|
|
+ std::cerr << "Received connection from " <<
|
|
|
+ config.nodes[node_num].name << "\n";
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for(size_t i=me+1; i<num_nodes; ++i) {
|
|
|
+ boost::system::error_code err;
|
|
|
+ tcp::socket nodesock(io_context);
|
|
|
+ while(1) {
|
|
|
+#ifdef VERBOSE_NET
|
|
|
+ std::cerr << "Connecting to " << config.nodes[i].name << "...\n";
|
|
|
+#endif
|
|
|
+ boost::asio::connect(nodesock,
|
|
|
+ resolver.resolve(config.nodes[i].listenhost,
|
|
|
+ config.nodes[i].listenport), err);
|
|
|
+ if (!err) break;
|
|
|
+ std::cerr << "Connection to " << config.nodes[i].name <<
|
|
|
+ " refused, will retry.\n";
|
|
|
+ sleep(1);
|
|
|
+ }
|
|
|
+ // Write 2 bytes to the socket to tell the peer node our node
|
|
|
+ // number
|
|
|
+ unsigned short node_num = (unsigned short)me;
|
|
|
+ boost::asio::write(nodesock,
|
|
|
+ boost::asio::buffer(&node_num, sizeof(node_num)));
|
|
|
+ nodesockets[i] = std::move(nodesock);
|
|
|
+#ifdef VERBOSE_NET
|
|
|
+ std::cerr << "Connected to " << config.nodes[i].name << "\n";
|
|
|
+#endif
|
|
|
+ }
|
|
|
}
|