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