Переглянути джерело

The nodes now all establish TCP connections with each other

Ian Goldberg 1 рік тому
батько
коміт
a476377b16
5 змінених файлів з 79 додано та 4 видалено
  1. 1 1
      App/config.cpp
  2. 1 1
      App/config.hpp
  3. 1 1
      App/mkconfig.py
  4. 68 1
      App/net.cpp
  5. 8 0
      App/net.hpp

+ 1 - 1
App/config.cpp

@@ -53,7 +53,7 @@ bool config_parse(Config &config, const std::string configstr,
                     if (!nentry.first.compare("name")) {
                         nc.name = nentry.second.get_value<std::string>();
                         if (!myname.compare(nc.name)) {
-                            config.mynodenum = config.nodes.size();
+                            config.my_node_num = config.nodes.size();
                             found_my_node = true;
                         }
                     } else if (!nentry.first.compare("pubkey")) {

+ 1 - 1
App/config.hpp

@@ -21,7 +21,7 @@ struct Config {
     // config for each node
     std::vector<NodeConfig> nodes;
     // Which node is this one?
-    size_t mynodenum;
+    size_t my_node_num;
 };
 
 bool config_parse(Config &config, const std::string configstr,

+ 1 - 1
App/mkconfig.py

@@ -31,7 +31,7 @@ def create_json(manifestfile, pubkeysfile, nodelist):
     if nodelist is None or len(nodelist) == 0:
         nodelist = manifest.keys()
     config = {}
-    if "params" in nodelist:
+    if "params" in manifest:
         config['params'] = manifest['params']
     config['nodes'] = []
     for node in nodelist:

+ 68 - 1
App/net.cpp

@@ -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
+    }
 }

+ 8 - 0
App/net.hpp

@@ -1,12 +1,20 @@
 #ifndef __NET_HPP__
 #define __NET_HPP__
 
+#include <vector>
+#include <optional>
 #include <boost/asio.hpp>
 
 #include "config.hpp"
 
+using boost::asio::ip::tcp;
+
 class NetIO {
     const Config &conf;
+    const NodeConfig &myconf;
+    size_t num_nodes;
+    size_t me;
+    std::vector<std::optional<tcp::socket>> nodesockets;
 
 public:
     NetIO(boost::asio::io_context &io_context, const Config &config);