From 8136448d75dd28e3ceb886ab64cc52762ad99dec Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nwpope@utu.fi>
Date: Sat, 23 Feb 2019 20:04:15 +0200
Subject: [PATCH] Add handshake protocol checks and add a tempory fix to nested
 wait problem

---
 net/include/ftl/net/dispatcher.hpp  |  1 -
 net/include/ftl/net/func_traits.hpp |  6 +++
 net/include/ftl/net/protocol.hpp    | 37 ++++++++++++++++++
 net/include/ftl/net/socket.hpp      |  9 +----
 net/src/listener.cpp                |  6 ++-
 net/src/net.cpp                     |  7 +++-
 net/src/socket.cpp                  | 60 +++++++++++++++++++++++++----
 net/test/net_raw.cpp                | 10 +++--
 net/test/rpc.cpp                    |  1 +
 9 files changed, 114 insertions(+), 23 deletions(-)

diff --git a/net/include/ftl/net/dispatcher.hpp b/net/include/ftl/net/dispatcher.hpp
index e652650f2..a2a8f332f 100644
--- a/net/include/ftl/net/dispatcher.hpp
+++ b/net/include/ftl/net/dispatcher.hpp
@@ -105,7 +105,6 @@ class Dispatcher {
 		    args_type args_real;
 		    args.convert(args_real);
 		    auto z = std::make_unique<msgpack::zone>();
-		    std::cout << "CALL " << ftl::internal::call(func, args_real) << std::endl;
 		    auto result = msgpack::object(ftl::internal::call(func, args_real), *z);
 		    return std::make_unique<msgpack::object_handle>(result, std::move(z));
 		}));
diff --git a/net/include/ftl/net/func_traits.hpp b/net/include/ftl/net/func_traits.hpp
index 3a4f83be2..ae12b335a 100644
--- a/net/include/ftl/net/func_traits.hpp
+++ b/net/include/ftl/net/func_traits.hpp
@@ -64,12 +64,18 @@ template <typename R, typename... Args> struct func_traits<R (*)(Args...)> {
     using args_type = std::tuple<typename std::decay<Args>::type...>;
 };
 
+//template <typename T>
+//auto bindThis(F f, T t) { return [f,t]()t.f(42, std::forward<decltype(arg)>(arg)); }
+
 template <typename T>
 struct func_kind_info : func_kind_info<decltype(&T::operator())> {};
 
 template <typename C, typename R, typename... Args>
 struct func_kind_info<R (C::*)(Args...)> : func_kind_info<R (*)(Args...)> {};
 
+//template <typename R, typename... Args>
+//struct func_kind_info<std::_Bind<R(Args...)>> : func_kind_info<R(*)(Args...)> {};
+
 template <typename C, typename R, typename... Args>
 struct func_kind_info<R (C::*)(Args...) const>
     : func_kind_info<R (*)(Args...)> {};
diff --git a/net/include/ftl/net/protocol.hpp b/net/include/ftl/net/protocol.hpp
index 6da75b48f..1f2429bf4 100644
--- a/net/include/ftl/net/protocol.hpp
+++ b/net/include/ftl/net/protocol.hpp
@@ -9,4 +9,41 @@
 
 #define FTL_PROTOCOL_P2P		0x1000
 
+namespace ftl {
+namespace net {
+
+static const uint32_t MAGIC = 0x23995621;
+
+static const uint8_t PATCH = 0;
+static const uint8_t MINOR = 0;
+static const uint8_t MAJOR = 1;
+
+inline uint32_t version(int maj, int min, int pat) {
+	return (maj << 16) | (min << 8) | pat;
+}
+
+inline uint32_t version() {
+	return version(MAJOR, MINOR, PATCH);
+}
+
+#pragma pack(push,1)
+
+struct Header {
+	uint32_t size;
+	uint32_t service;
+};
+
+struct Handshake {
+	uint32_t magic;
+	uint32_t version;
+	char peerid[16];
+};
+
+#pragma pack(pop)
+
+
+
+};
+};
+
 #endif // _FTL_NET_PROTOCOL_HPP_
diff --git a/net/include/ftl/net/socket.hpp b/net/include/ftl/net/socket.hpp
index cea77f25a..08f8c25c5 100644
--- a/net/include/ftl/net/socket.hpp
+++ b/net/include/ftl/net/socket.hpp
@@ -22,13 +22,6 @@
 namespace ftl {
 namespace net {
 
-#pragma pack(push,1)
-struct Header {
-	uint32_t size;
-	uint32_t service;
-};
-#pragma pack(pop)
-
 class Socket {
 	public:
 	Socket(const char *uri);
@@ -139,6 +132,8 @@ class Socket {
 	bool connected_;
 	std::map<int, std::function<void(msgpack::object&)>> callbacks_;
 	ftl::net::Dispatcher disp_;
+	uint32_t version_;
+	std::string peerid_;
 	
 	void _connected();
 	void _updateURI();
diff --git a/net/src/listener.cpp b/net/src/listener.cpp
index 3b2808fd9..016af2185 100644
--- a/net/src/listener.cpp
+++ b/net/src/listener.cpp
@@ -111,8 +111,10 @@ Listener::~Listener() {
 }
 
 void Listener::connection(shared_ptr<Socket> &s) {
-	std::string hs1("HELLO");
-	s->send(FTL_PROTOCOL_HS1, hs1);
+	ftl::net::Handshake hs1;
+	hs1.magic = ftl::net::MAGIC;
+	hs1.version = ftl::net::version();
+	s->send(FTL_PROTOCOL_HS1, std::string((char*)&hs1, sizeof(hs1)));
 	LOG(INFO) << "Handshake initiated with " << s->getURI();
 	for (auto h : handler_connect_) h(s);
 }
diff --git a/net/src/net.cpp b/net/src/net.cpp
index 160a47ef6..f3f329a08 100644
--- a/net/src/net.cpp
+++ b/net/src/net.cpp
@@ -119,10 +119,13 @@ bool _run(bool blocking, bool nodelay) {
 		active = blocking;
 
 		//Some kind of error occured, it is usually possible to recover from this.
-		if (selres <= 0) {
-			//std::cout << "SELECT ERROR" << std::endl;
+		if (selres < 0) {
+			std::cout << "SELECT ERROR " << selres << std::endl;
 			//return false;
 			continue;
+		} else if (selres == 0) {
+			// Timeout, nothing to do...
+			continue;
 		}
 
 		//If connection request is waiting
diff --git a/net/src/socket.cpp b/net/src/socket.cpp
index 10610cf6c..945763136 100644
--- a/net/src/socket.cpp
+++ b/net/src/socket.cpp
@@ -201,6 +201,7 @@ void Socket::error() {
 bool Socket::data() {
 	//Read data from socket
 	size_t n = 0;
+	int c = 0;
 	uint32_t len = 0;
 
 	if (pos_ < 4) {
@@ -230,18 +231,25 @@ bool Socket::data() {
 			}
 		} else if (rc == EWOULDBLOCK || rc == 0) {
 			// Data not yet available
+			if (c == 0) {
+				LOG(INFO) << "Socket disconnected " << uri_;
+				close();
+			}
 			return false;
 		} else {
 			LOG(ERROR) << "Socket: " << uri_ << " - error " << rc;
 			close();
 			return false;
 		}
+		c++;
 	}
 
 	// Route the message...
 	uint32_t service = ((uint32_t*)buffer_)[1];
 	auto d = std::string(buffer_+8, len-4);
 	
+	pos_ = 0; // DODGY, processing messages inside handlers is dangerous.
+	
 	if (service == FTL_PROTOCOL_HS1 && !connected_) {
 		handshake1(d);
 	} else if (service == FTL_PROTOCOL_HS2 && !connected_) {
@@ -257,23 +265,59 @@ bool Socket::data() {
 		} else {
 			LOG(ERROR) << "Unrecognised service request (" << service << ") from " << uri_;
 		}
-	} 
-
-	pos_ = 0;
+	}
 
 	return true;
 }
 
 void Socket::handshake1(const std::string &d) {
-	// TODO Verify data
-	std::string hs2("HELLO");
-	send(FTL_PROTOCOL_HS2, hs2);
-	LOG(INFO) << "Handshake confirmed from " << uri_;
+	ftl::net::Handshake *hs;
+	if (d.size() != sizeof(ftl::net::Handshake)) {
+		LOG(ERROR) << "Handshake failed for " << uri_;
+		close();
+		return;
+	}
+	
+	hs = (ftl::net::Handshake*)d.data();
+	if (hs->magic != ftl::net::MAGIC) {
+		LOG(ERROR) << "Handshake magic failed for " << uri_;
+		close();
+		return;
+	}
+	
+	version_ = (hs->version > ftl::net::version()) ?
+			ftl::net::version() :
+			hs->version;
+	peerid_ = std::string(&hs->peerid[0],16);
+	
+	ftl::net::Handshake hs2;
+	hs2.magic = ftl::net::MAGIC;
+	hs2.version = version_;
+	// TODO Set peerid;
+	send(FTL_PROTOCOL_HS2, std::string((char*)&hs2, sizeof(hs2)));
+	LOG(INFO) << "Handshake v" << version_ << " confirmed from " << uri_;
 	_connected();
 }
 
 void Socket::handshake2(const std::string &d) {
-	// TODO Verify data
+	ftl::net::Handshake *hs;
+	if (d.size() != sizeof(ftl::net::Handshake)) {
+		LOG(ERROR) << "Handshake failed for " << uri_;
+		close();
+		return;
+	}
+	
+	hs = (ftl::net::Handshake*)d.data();
+	if (hs->magic != ftl::net::MAGIC) {
+		LOG(ERROR) << "Handshake magic failed for " << uri_;
+		close();
+		return;
+	}
+	
+	version_ = (hs->version > ftl::net::version()) ?
+			ftl::net::version() :
+			hs->version;
+	peerid_ = std::string(&hs->peerid[0],16);
 	LOG(INFO) << "Handshake finalised for " << uri_;
 	_connected();
 }
diff --git a/net/test/net_raw.cpp b/net/test/net_raw.cpp
index 5fc57e492..7c559d97c 100644
--- a/net/test/net_raw.cpp
+++ b/net/test/net_raw.cpp
@@ -186,7 +186,11 @@ void accept_connection() {
 
 		//Finally accept this client connection.
 		csock = accept(ssock, (sockaddr*)&addr, (socklen_t*)&rsize);
-		mocksend(csock, FTL_PROTOCOL_HS1, "HELLO");
+		
+		ftl::net::Handshake hs1;
+		hs1.magic = ftl::net::MAGIC;
+		hs1.version = ftl::net::version();
+		mocksend(csock, FTL_PROTOCOL_HS1, std::string((char*)&hs1, sizeof(hs1)));
 	} else {
 
 	}
@@ -340,8 +344,8 @@ TEST_CASE("Socket.bind(int)", "[net]") {
 			msg++;	
 		});
 
-		ftl::net::wait();
-		ftl::net::wait();
+		ftl::net::wait(); // MSG 1
+		ftl::net::wait(); // MSG 2
 		REQUIRE(msg == 2);
 	}
 
diff --git a/net/test/rpc.cpp b/net/test/rpc.cpp
index d07067a83..e48d775ec 100644
--- a/net/test/rpc.cpp
+++ b/net/test/rpc.cpp
@@ -48,6 +48,7 @@ extern ssize_t recv(int sd, void *buf, size_t n, int f) {
 }
 
 extern ssize_t writev(int sd, const struct iovec *v, int cnt) {
+	// TODO Use count incase more sources exist...
 	size_t len = v[0].iov_len+v[1].iov_len;
 	char buf[len];
 	std::memcpy(&buf[0],v[0].iov_base,v[0].iov_len);
-- 
GitLab