net.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #include <iostream>
  2. #include "config.hpp"
  3. #include "net.hpp"
  4. NetIO::NetIO(boost::asio::io_context &io_context, const Config &config)
  5. : conf(config), myconf(config.nodes[config.my_node_num])
  6. {
  7. num_nodes = conf.nodes.size();
  8. nodesockets.resize(num_nodes);
  9. me = conf.my_node_num;
  10. // Node number n will accept connections from nodes 0, ..., n-1 and
  11. // make connections to nodes n+1, ..., num_nodes-1. This is all
  12. // single threaded, but it doesn't deadlock because node 0 isn't
  13. // waiting for any incoming connections, so it immediately makes
  14. // outgoing connections. When it connects to node 1, that node
  15. // accepts its (only) incoming connection, and then starts making
  16. // its outgoing connections, etc.
  17. tcp::resolver resolver(io_context);
  18. tcp::acceptor acceptor(io_context,
  19. resolver.resolve(myconf.listenhost, myconf.listenport)->endpoint());
  20. for(size_t i=0; i<me; ++i) {
  21. #ifdef VERBOSE_NET
  22. std::cerr << "Accepting number " << i << "\n";
  23. #endif
  24. tcp::socket nodesock = acceptor.accept();
  25. #ifdef VERBOSE_NET
  26. std::cerr << "Accepted number " << i << "\n";
  27. #endif
  28. // Read 2 bytes from the socket, which will be the
  29. // connecting node's node number
  30. unsigned short node_num;
  31. boost::asio::read(nodesock,
  32. boost::asio::buffer(&node_num, sizeof(node_num)));
  33. if (node_num >= num_nodes) {
  34. std::cerr << "Received bad node number\n";
  35. } else {
  36. nodesockets[node_num] = std::move(nodesock);
  37. #ifdef VERBOSE_NET
  38. std::cerr << "Received connection from " <<
  39. config.nodes[node_num].name << "\n";
  40. #endif
  41. }
  42. }
  43. for(size_t i=me+1; i<num_nodes; ++i) {
  44. boost::system::error_code err;
  45. tcp::socket nodesock(io_context);
  46. while(1) {
  47. #ifdef VERBOSE_NET
  48. std::cerr << "Connecting to " << config.nodes[i].name << "...\n";
  49. #endif
  50. boost::asio::connect(nodesock,
  51. resolver.resolve(config.nodes[i].listenhost,
  52. config.nodes[i].listenport), err);
  53. if (!err) break;
  54. std::cerr << "Connection to " << config.nodes[i].name <<
  55. " refused, will retry.\n";
  56. sleep(1);
  57. }
  58. // Write 2 bytes to the socket to tell the peer node our node
  59. // number
  60. unsigned short node_num = (unsigned short)me;
  61. boost::asio::write(nodesock,
  62. boost::asio::buffer(&node_num, sizeof(node_num)));
  63. nodesockets[i] = std::move(nodesock);
  64. #ifdef VERBOSE_NET
  65. std::cerr << "Connected to " << config.nodes[i].name << "\n";
  66. #endif
  67. }
  68. }