aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--libcmix-network/CMakeLists.txt2
-rw-r--r--libcmix-network/acceptor.cpp1
-rw-r--r--libcmix-network/client.cpp5
-rw-r--r--libcmix-network/client.hpp4
-rw-r--r--libcmix-network/connect.cpp38
-rw-r--r--libcmix-network/connect.hpp3
-rw-r--r--libcmix-network/uriparser.cpp3
-rw-r--r--libcmix-network/uriparser.hpp59
-rw-r--r--libcmix-protobuf/CMakeLists.txt19
-rw-r--r--libcmix-protobuf/cmix.proto3
-rw-r--r--liblog/logging.cpp3
-rw-r--r--network-handler/nodemanager.cpp2
-rw-r--r--network-handler/nodemanager.hpp1
-rw-r--r--node/CMakeLists.txt1
-rw-r--r--node/main.cpp51
-rw-r--r--node/nextnode.cpp27
-rw-r--r--node/nextnode.hpp4
-rw-r--r--node/node.cpp52
-rw-r--r--node/node.hpp17
20 files changed, 274 insertions, 23 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d1cbc8..2c1710c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,8 @@ add_subdirectory(libcmix)
add_subdirectory(liblog)
add_subdirectory(libcmix-network)
+add_subdirectory(libcmix-protobuf)
+
add_subdirectory(network-handler)
add_subdirectory(node)
diff --git a/libcmix-network/CMakeLists.txt b/libcmix-network/CMakeLists.txt
index 6986eea..2574e82 100644
--- a/libcmix-network/CMakeLists.txt
+++ b/libcmix-network/CMakeLists.txt
@@ -7,6 +7,7 @@ add_library(cmix-network
server.hpp server.cpp
client.hpp client.cpp
nodeclient.hpp nodeclient.cpp
+ uriparser.hpp uriparser.cpp
)
target_compile_options(cmix-network
@@ -22,6 +23,7 @@ target_link_libraries(cmix-network
PUBLIC Boost::system
PUBLIC ${CMAKE_THREAD_LIBS_INIT}
PRIVATE cmix
+ PRIVATE log
)
if(WIN32)
diff --git a/libcmix-network/acceptor.cpp b/libcmix-network/acceptor.cpp
index 34b5f0e..69b2807 100644
--- a/libcmix-network/acceptor.cpp
+++ b/libcmix-network/acceptor.cpp
@@ -22,7 +22,6 @@ void accept_connection(tcp::acceptor& acceptor, std::shared_ptr<tcp::socket> soc
ss << ec;
throw std::runtime_error(ss.str());
}
-
}
void accept_loop(tcp::acceptor& acceptor, std::function<void(tcp::socket&&)> f)
diff --git a/libcmix-network/client.cpp b/libcmix-network/client.cpp
index 544dd87..ce9fd4d 100644
--- a/libcmix-network/client.cpp
+++ b/libcmix-network/client.cpp
@@ -1,5 +1,7 @@
#include "client.hpp"
+#include "logging.hpp"
+
#include <boost/asio/placeholders.hpp>
#include <boost/bind.hpp>
@@ -19,10 +21,11 @@ void Client::handle_receive(MessageHandler message_handler, const error_code &ec
buffer.commit(read_bytes);
std::istream is(&buffer);
+ BOOST_LOG_TRIVIAL(trace) << "handling receive";
+
if(!ec) {
std::vector<uint8_t> data(std::istream_iterator<uint8_t>(is), {});
message_handler(data);
- receive(message_handler);
} else {
if(done) {
done();
diff --git a/libcmix-network/client.hpp b/libcmix-network/client.hpp
index 2b6a6df..46b989d 100644
--- a/libcmix-network/client.hpp
+++ b/libcmix-network/client.hpp
@@ -10,8 +10,10 @@ public:
typedef std::function<void(void)> OnDoneFT;
typedef std::function<void(std::vector<uint8_t>)> MessageHandler;
-private:
+protected:
boost::asio::ip::tcp::socket socket;
+
+private:
boost::asio::streambuf buffer;
OnDoneFT done;
diff --git a/libcmix-network/connect.cpp b/libcmix-network/connect.cpp
index 679748e..bf200d5 100644
--- a/libcmix-network/connect.cpp
+++ b/libcmix-network/connect.cpp
@@ -1,23 +1,24 @@
#include "connect.hpp"
+#include "logging.hpp"
+
#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/address.hpp>
using namespace boost::asio::ip;
using boost::asio::io_service;
-boost::asio::ip::tcp::socket connect(std::string host, std::string port, io_service& io_service) {
+boost::asio::ip::tcp::socket connect(std::string host, io_service& io_service) {
boost::asio::ip::basic_resolver<tcp> resolver(io_service);
- boost::asio::ip::basic_resolver_query<tcp> query(host, port);
- boost::asio::ip::basic_endpoint<tcp> endpoint;
+ boost::asio::ip::basic_resolver_query<tcp> query(host, "");
for(auto it = resolver.resolve(query); it != boost::asio::ip::tcp::resolver::iterator(); ++it)
{
- endpoint = *it;
boost::system::error_code ec;
boost::asio::ip::tcp::socket socket(io_service);
- socket.connect(endpoint, ec);
+ socket.connect(*it, ec);
if(ec) {
continue;
} else {
@@ -27,3 +28,30 @@ boost::asio::ip::tcp::socket connect(std::string host, std::string port, io_serv
throw std::runtime_error("None of the supplied endpoints responded");
}
+
+void async_connect_iteration(tcp::socket& socket, boost::asio::ip::tcp::resolver::iterator it, std::function<void()> on_connect) {
+ if(it == boost::asio::ip::tcp::resolver::iterator()) {
+ throw std::runtime_error("None of the supplied endpoints responded");
+ }
+
+ auto handler = [&socket, it, on_connect](boost::system::error_code const& ec) {
+ if(ec) {
+ BOOST_LOG_TRIVIAL(info) << ec << std::endl;
+ async_connect_iteration(socket, std::next(it), on_connect);
+ } else {
+ on_connect();
+ }
+ };
+
+ socket.async_connect(*it, handler);
+}
+
+void async_connect(tcp::socket& socket, std::string host, std::string next_port, std::function<void()> on_connect)
+{
+ boost::asio::ip::basic_resolver<tcp> resolver(socket.get_io_service());
+ boost::asio::ip::basic_resolver_query<tcp> query(host, next_port);
+
+ auto it = resolver.resolve(query);
+
+ async_connect_iteration(socket, it, on_connect);
+}
diff --git a/libcmix-network/connect.hpp b/libcmix-network/connect.hpp
index 7f5b5c3..071ed9b 100644
--- a/libcmix-network/connect.hpp
+++ b/libcmix-network/connect.hpp
@@ -3,4 +3,5 @@
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
-boost::asio::ip::tcp::socket connect(std::string host, std::string port, boost::asio::io_service& io_service);
+boost::asio::ip::tcp::socket connect(std::string host, boost::asio::io_service& io_service);
+void async_connect(boost::asio::ip::tcp::socket& socket, std::string host, std::string next_port, std::function<void()> on_connect);
diff --git a/libcmix-network/uriparser.cpp b/libcmix-network/uriparser.cpp
new file mode 100644
index 0000000..9cea452
--- /dev/null
+++ b/libcmix-network/uriparser.cpp
@@ -0,0 +1,3 @@
+#include "uriparser.hpp"
+
+
diff --git a/libcmix-network/uriparser.hpp b/libcmix-network/uriparser.hpp
new file mode 100644
index 0000000..c46b70a
--- /dev/null
+++ b/libcmix-network/uriparser.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <string>
+#include <regex>
+#include <iostream>
+
+struct Uri {
+ std::string scheme;
+ std::string username;
+ std::string password;
+ std::string host;
+ std::string port;
+ std::string query;
+ std::string hash;
+};
+
+Uri parse_uri(std::string str) {
+ std::string scheme = "(?:(.+?)://)?";
+ std::string uname_pass = "(?:(.*?)?(?::(.*?))@)?";
+ std::string host = "(.+?)";
+ std::string port = "(?::(\\d+?))?";
+ std::string query = "(?:\\?(.+?))?";
+ std::string hash = "(?:#(.+?))?";
+
+ std::regex expr("^" + scheme + uname_pass + host + port + query + hash + "$");
+ std::smatch matches;
+ std::regex_match(str, matches, expr);
+
+ return {
+ matches[1].str(),
+ matches[2].str(),
+ matches[3].str(),
+ matches[4].str(),
+ matches[5].str(),
+ matches[6].str(),
+ matches[7].str()
+ };
+}
+
+std::string debug_uri(Uri uri) {
+ std::stringstream ss;
+ ss << "scheme: " << uri.scheme << std::endl
+ << "username: " << uri.username << std::endl
+ << "password: " << uri.password << std::endl
+ << "host: " << uri.host << std::endl
+ << "port: " << uri.port << std::endl
+ << "query: " << uri.query << std::endl
+ << "hash: " << uri.hash << std::endl;
+ return ss.str();
+}
+
+std::string uri_to_string(Uri uri) {
+ return
+ (!uri.scheme.empty() ? uri.scheme + "://" : "") +
+ (!uri.username.empty() ? uri.username + (!uri.password.empty() ? ":" + uri.password : "") + "@" : "") +
+ uri.host +
+ (!uri.port.empty() ? ":" + uri.port : "") +
+ (!uri.query.empty() ? "?" + uri.query : "");
+}
diff --git a/libcmix-protobuf/CMakeLists.txt b/libcmix-protobuf/CMakeLists.txt
new file mode 100644
index 0000000..f2a8f3d
--- /dev/null
+++ b/libcmix-protobuf/CMakeLists.txt
@@ -0,0 +1,19 @@
+find_package(Protobuf REQUIRED)
+
+set(proto_files cmix.proto)
+
+protobuf_generate_cpp(proto_sources proto_headers
+ ${proto_files}
+)
+
+add_library(cmix-protobuf
+ ${proto_files}
+ ${proto_headers} ${proto_sources}
+)
+
+target_include_directories(cmix-protobuf
+ PUBLIC ${PROTOBUF_INCLUDE_DIRS}
+ PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+target_link_libraries(cmix-protobuf ${PROTOBUF_LIBRARIES}) \ No newline at end of file
diff --git a/libcmix-protobuf/cmix.proto b/libcmix-protobuf/cmix.proto
new file mode 100644
index 0000000..f0c1dc3
--- /dev/null
+++ b/libcmix-protobuf/cmix.proto
@@ -0,0 +1,3 @@
+message initialization {
+ required bytes public_share = 1;
+}
diff --git a/liblog/logging.cpp b/liblog/logging.cpp
index c92247c..6bbf070 100644
--- a/liblog/logging.cpp
+++ b/liblog/logging.cpp
@@ -18,7 +18,8 @@ void init_logging(boost::log::trivial::severity_level log_level)
(
boost::log::keywords::file_name = "node%N.log",
boost::log::keywords::rotation_size = 10 * 1024 * 1024,
- boost::log::keywords::format = "[%Severity%] (%TimeStamp%): %Message%"
+ boost::log::keywords::format = "[%Severity%] (%TimeStamp%): %Message%",
+ boost::log::keywords::auto_flush = true
);
boost::log::core::get()->set_filter
diff --git a/network-handler/nodemanager.cpp b/network-handler/nodemanager.cpp
index 165cb3b..179f239 100644
--- a/network-handler/nodemanager.cpp
+++ b/network-handler/nodemanager.cpp
@@ -9,6 +9,6 @@ NodeManager::NodeManager(std::vector<ConnectionInfo> connections)
, nodes()
{
for(auto&& ci : connections) {
- nodes.emplace_back(connect(ci.host, ci.port, io_service));
+ nodes.emplace_back(connect(ci.host, io_service));
}
}
diff --git a/network-handler/nodemanager.hpp b/network-handler/nodemanager.hpp
index 651e6a4..8f6e7af 100644
--- a/network-handler/nodemanager.hpp
+++ b/network-handler/nodemanager.hpp
@@ -8,7 +8,6 @@
struct ConnectionInfo {
std::string host;
- std::string port;
};
class NodeManager
diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt
index a4e1f09..c3c8e46 100644
--- a/node/CMakeLists.txt
+++ b/node/CMakeLists.txt
@@ -17,4 +17,5 @@ target_link_libraries(node
PRIVATE log
PRIVATE cmix
PRIVATE cmix-network
+ PRIVATE cmix-protobuf
)
diff --git a/node/main.cpp b/node/main.cpp
index 970e150..1327ac5 100644
--- a/node/main.cpp
+++ b/node/main.cpp
@@ -1,4 +1,53 @@
-int main() {
+#include "node.hpp"
+#include "uriparser.hpp"
+#include "logging.hpp"
+#include <boost/program_options.hpp>
+
+#include <iostream>
+
+int main(int argc, char* argv[]) {
+ namespace po = boost::program_options;
+
+ init_logging(boost::log::trivial::severity_level::trace);
+
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "produce help message.")
+ ("port,p", po::value<uint16_t>()->default_value(9200), "Set listening port.")
+ ("enable_v4", po::value<bool>()->default_value(true), "Enable/disable ipv4 accept support.")
+ ("interface4,4", po::value<std::string>()->default_value("0.0.0.0"), "Set the ipv4 address to listen on.")
+ ("enable_v6", po::value<bool>()->default_value(true), "Enable/disable ipv6 accept support.")
+ ("interface6,6", po::value<std::string>()->default_value("::"), "Set the ipv6 address to listen on.")
+ ("next_node,n", po::value<std::string>()->required(), "The address of the next node in the network")
+ ("first,f", "This is the first node and will be the communication point for the clients.")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << desc << "\n";
+ return 0;
+ }
+
+ bool en4 = vm["enable_v4"].as<bool>();
+ std::string if4 = vm["interface4"].as<std::string>();
+ bool en6 = vm["enable_v6"].as<bool>();
+ std::string if6 = vm["interface6"].as<std::string>();
+ uint16_t port = vm["port"].as<uint16_t>();
+
+ ListenSettings lsettings{en4, if4, en6, if6, port};
+
+ bool is_first = bool(vm.count("first"));
+ std::string next_node = vm["next_node"].as<std::string>();
+
+ Uri uri = parse_uri(next_node);
+
+ NodeNetworkSettings nsettings{is_first, uri.host, uri.port};
+
+ Node node(lsettings, nsettings);
+ node.run();
}
diff --git a/node/nextnode.cpp b/node/nextnode.cpp
index 3045462..d38200d 100644
--- a/node/nextnode.cpp
+++ b/node/nextnode.cpp
@@ -1,7 +1,34 @@
#include "nextnode.hpp"
+#include "connect.hpp"
+
+#include "logging.hpp"
+
using namespace boost::asio::ip;
NextNode::NextNode(tcp::socket&& socket)
: Client(std::move(socket))
{}
+
+void NextNode::send(std::string message)
+{
+ auto handler = [](boost::system::error_code const& ec, std::size_t bytes_transferred) {
+ BOOST_LOG_TRIVIAL(trace) << "sent message";
+ if(ec) {
+ BOOST_LOG_TRIVIAL(fatal) << ec;
+ throw std::runtime_error("unable to send message");
+ }
+ };
+
+ socket.async_send(boost::asio::buffer(message), 0, handler);
+}
+
+void NextNode::connect(std::string next_host, std::string next_port, std::function<void ()> on_connect)
+{
+ async_connect(socket, next_host, next_port, on_connect);
+}
+
+void NextNode::close()
+{
+ socket.close();
+}
diff --git a/node/nextnode.hpp b/node/nextnode.hpp
index c1ce6a1..42206bb 100644
--- a/node/nextnode.hpp
+++ b/node/nextnode.hpp
@@ -8,5 +8,9 @@ class NextNode : public Client
{
public:
NextNode(boost::asio::ip::tcp::socket&& socket);
+
+ void send(std::string message);
+ void connect(std::string next_host, std::string next_port, std::function<void()> on_connect);
+ void close();
};
diff --git a/node/node.cpp b/node/node.cpp
index 4b4bc2b..b33f8a5 100644
--- a/node/node.cpp
+++ b/node/node.cpp
@@ -1,17 +1,31 @@
#include "node.hpp"
-#include "connect.hpp"
+
+#include "logging.hpp"
+
+using namespace boost::asio::ip;
Node::Node(ListenSettings const& listen_settings, NodeNetworkSettings network_settings)
: io_service()
, server(io_service, listen_settings, [this](boost::asio::ip::tcp::socket&& socket){accept_handler(std::move(socket));})
, clients()
-, next_node(connect(network_settings.next_host, network_settings.next_port, io_service))
+, network_settings(network_settings)
+, next_node(tcp::socket(io_service))
, api(get_curve25519_implementation())
, keypair(api.create_key_pair())
+, network_pub_key()
{
- if(network_settings.is_first) {
- start_initialisation();
- }
+ auto on_connect = [this, network_settings](){
+ BOOST_LOG_TRIVIAL(trace) << "is first: " << std::boolalpha << network_settings.is_first;
+ if(network_settings.is_first) {
+ start_initialisation();
+ }
+ };
+
+ next_node.connect(network_settings.next_host, network_settings.next_port, on_connect);
+}
+
+Node::~Node() {
+ api.free_key_pair(keypair);
}
void Node::accept_handler(boost::asio::ip::tcp::socket&& socket)
@@ -24,6 +38,32 @@ void Node::accept_handler(boost::asio::ip::tcp::socket&& socket)
clients.erase(it);
}
);
+}
+
+void Node::start_initialisation() {
+ initialization init;
+ init.set_public_share(keypair.pub, keypair.pub_len);
+
+ BOOST_LOG_TRIVIAL(trace) << "length of keypair.pub: " << keypair.pub_len;
+
+ std::string message;
+ init.SerializeToString(&message);
+ BOOST_LOG_TRIVIAL(trace) << init.DebugString();
+ next_node.send(message);
+
+ auto f = [this](std::vector<uint8_t> bytes) {
+ network_pub_key = bytes;
+
+ if(network_settings.is_first) {
+ start_precomputation();
+ }
+ };
+
+ BOOST_LOG_TRIVIAL(trace) << "number of clients: " << clients.size();
+ for(auto&& client : clients) {
+ client.receive(f);
+ }
+}
- clients.back().receive();
+void Node::start_precomputation() {
}
diff --git a/node/node.hpp b/node/node.hpp
index 9e321df..5668dec 100644
--- a/node/node.hpp
+++ b/node/node.hpp
@@ -7,6 +7,8 @@
#include "api.h"
#include "curve25519.h"
+#include "cmix.pb.h"
+
#include <boost/asio/io_service.hpp>
#include <list>
@@ -21,20 +23,27 @@ class Node
{
boost::asio::io_service io_service;
Server server;
- std::list<NodeClient> clients;
+ std::list<Client> clients;
+
+ NodeNetworkSettings network_settings;
NextNode next_node;
Api api;
KeyPair keypair;
+ std::vector<uint8_t> network_pub_key;
void accept_handler(boost::asio::ip::tcp::socket&& socket);
- void start_initialisation() {
-
- }
+ void start_precomputation();
+ void start_initialisation();
public:
Node(ListenSettings const& listen_settings, NodeNetworkSettings network_settings);
+ ~Node();
+
+ void run() {
+ io_service.run();
+ }
};