From af04fc3ccbe1243dbb5472b2b2a9a1ff686c29c7 Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nwpope@utu.fi>
Date: Wed, 3 Apr 2019 08:25:17 +0300
Subject: [PATCH] cppcheck on net module and update main.cpp to work

---
 net/cpp/CMakeLists.txt             |  6 ++++
 net/cpp/include/ftl/net/p2p.hpp    | 14 ++++++--
 net/cpp/include/ftl/net/socket.hpp |  7 ++++
 net/cpp/include/ftl/uuid.hpp       | 19 +++++++----
 net/cpp/src/main.cpp               | 18 ++++++----
 net/cpp/src/socket.cpp             | 53 ++++++++++++++++++++++++++----
 net/cpp/test/CMakeLists.txt        |  3 ++
 7 files changed, 98 insertions(+), 22 deletions(-)

diff --git a/net/cpp/CMakeLists.txt b/net/cpp/CMakeLists.txt
index 2eadfb088..1f80ac614 100644
--- a/net/cpp/CMakeLists.txt
+++ b/net/cpp/CMakeLists.txt
@@ -9,6 +9,8 @@ set(NETSOURCE
 	src/socket.cpp
 	src/dispatcher.cpp
 	src/protocol.cpp
+	src/ws_internal.cpp
+	src/p2p.cpp
 )
 
 #check_include_file("uriparser/Uri.h" HAVE_URI_H)
@@ -20,4 +22,8 @@ check_function_exists(uriParseSingleUriA HAVE_URIPARSESINGLE)
 add_library(net ${NETSOURCE})
 target_link_libraries(net pthread)
 
+add_executable(net-cli src/main.cpp)
+target_link_libraries(net-cli "${PROJECT_BINARY_DIR}/net/cpp/libnet.a" ${GLOG_LIBRARIES} ${URIPARSER_LIBRARIES} pthread readline uuid)
+add_dependencies(net-cli net)
+
 ADD_SUBDIRECTORY(test)
diff --git a/net/cpp/include/ftl/net/p2p.hpp b/net/cpp/include/ftl/net/p2p.hpp
index 76f2ca0ca..f9547dbde 100644
--- a/net/cpp/include/ftl/net/p2p.hpp
+++ b/net/cpp/include/ftl/net/p2p.hpp
@@ -23,12 +23,20 @@ namespace net {
  */
 class P2P : public ftl::net::Protocol {
 	public:
-	P2P(const char *uri);
-	P2P(const std::string &uri);
+	explicit P2P(const char *uri);
+	explicit P2P(const std::string &uri);
 	
 	void addPeer(std::shared_ptr<ftl::net::Socket> s) { peers_.push_back(s); };
+	void addPeer(const std::string &uri) {
+		auto s = ftl::net::connect(uri.c_str());
+		if (s->isValid()) peers_.push_back(s);
+	}
+	
+	const std::vector<std::shared_ptr<ftl::net::Socket>> &getPeers() const {
+		return peers_;
+	}
 	
-	const UUID &id() const { return id_; }
+	const ftl::UUID &id() const { return id_; }
 	
 	/**
 	 * Bind a member function as an rpc "find one" across peers function.
diff --git a/net/cpp/include/ftl/net/socket.hpp b/net/cpp/include/ftl/net/socket.hpp
index a1c062a37..704ef00cc 100644
--- a/net/cpp/include/ftl/net/socket.hpp
+++ b/net/cpp/include/ftl/net/socket.hpp
@@ -5,6 +5,7 @@
 #include <glog/logging.h>
 #include <ftl/net.hpp>
 #include <ftl/net/protocol.hpp>
+#include <ftl/uri.hpp>
 
 #ifndef WIN32
 #define INVALID_SOCKET -1
@@ -78,6 +79,8 @@ class Socket {
 	 * the same as the initial connection string on the client.
 	 */
 	std::string getURI() const { return uri_; };
+	
+	std::string to_string() const { return peerid_; };
 			
 	/**
 	 * Non-blocking Remote Procedure Call using a callback function.
@@ -166,6 +169,7 @@ class Socket {
 	bool valid_;
 	bool connected_;
 	int sock_;
+	ftl::URI::scheme_t scheme_;
 	
 	// Receive buffers
 	size_t pos_;
@@ -198,6 +202,9 @@ class Socket {
 
 template <typename... ARGS>
 int Socket::send(uint32_t s, ARGS... args) {
+	// Leave a blank entry for websocket header
+	if (scheme_ == ftl::URI::SCHEME_WS) send_vec_.push_back({nullptr,0});
+	
 	header_w_->service = s;
 	header_w_->size = 4;
 	send_vec_.push_back({header_w_,sizeof(ftl::net::Header)});
diff --git a/net/cpp/include/ftl/uuid.hpp b/net/cpp/include/ftl/uuid.hpp
index e8bca1702..4a042c9cd 100644
--- a/net/cpp/include/ftl/uuid.hpp
+++ b/net/cpp/include/ftl/uuid.hpp
@@ -24,17 +24,24 @@ namespace ftl {
 #else
 			uuid_generate(uuid_);
 #endif
-		};
-		UUID(int u) { memset(&uuid_,u,16); };
-		UUID(const UUID &u) { memcpy(&uuid_,&u.uuid_,16); }
+		}
+		explicit UUID(int u) { memset(&uuid_,u,16); }
+		UUID(const ftl::UUID &u) { memcpy(&uuid_,&u.uuid_,16); }
 		
-		bool operator==(const UUID &u) const { return memcmp(&uuid_,&u.uuid_,16) == 0; }
-		bool operator!=(const UUID &u) const { return memcmp(&uuid_,&u.uuid_,16) != 0; }
+		UUID &operator=(const UUID &u)  {
+			memcpy(&uuid_,&u.uuid_,16); return *this;
+		}
+		bool operator==(const UUID &u) const {
+			return memcmp(&uuid_,&u.uuid_,16) == 0;
+		}
+		bool operator!=(const UUID &u) const {
+			return memcmp(&uuid_,&u.uuid_,16) != 0;
+		}
 		
 		/**
 		 * Get a raw data string.
 		 */
-		std::string str() const { return std::string((char*)&uuid_,16); };
+		std::string str() const { return std::string((char*)&uuid_,16); }
 		const unsigned char *raw() const { return (const unsigned char*)&uuid_; }
 		
 		/**
diff --git a/net/cpp/src/main.cpp b/net/cpp/src/main.cpp
index a63f538a6..34c1a1d73 100644
--- a/net/cpp/src/main.cpp
+++ b/net/cpp/src/main.cpp
@@ -13,7 +13,7 @@ using ftl::net::P2P;
 using ftl::net::Listener;
 using ftl::net::Socket;
 
-static P2P p2p("ftl://cli");
+static P2P *p2p;
 static shared_ptr<Listener> listener = nullptr;
 static volatile bool stop = false;
 
@@ -25,12 +25,12 @@ void handle_options(const char ***argv, int *argc) {
 		if (cmd.find("--peer=") == 0) {
 			cmd = cmd.substr(cmd.find("=")+1);
 			//std::cout << "Peer added " << cmd.substr(cmd.find("=")+1) << std::endl;
-			p2p.addPeer(cmd);
+			p2p->addPeer(cmd);
 		} else if (cmd.find("--listen=") == 0) {
 			cmd = cmd.substr(cmd.find("=")+1);
 			listener = ftl::net::listen(cmd.c_str());
-			if (listener) listener->setProtocol(&p2p);
-			listener->onConnection([](shared_ptr<Socket> &s) { p2p.addPeer(s); });
+			if (listener) listener->setProtocol(p2p);
+			listener->onConnection([](shared_ptr<Socket> &s) { p2p->addPeer(s); });
 		}
 		
 		(*argc)--;
@@ -49,12 +49,12 @@ void handle_command(const char *l) {
 		stop = true;
 	} else if (cmd.find("peer ") == 0) {
 		cmd = cmd.substr(cmd.find(" ")+1);
-		p2p.addPeer(cmd);
+		p2p->addPeer(cmd);
 	} else if (cmd.find("list ") == 0) {
 		cmd = cmd.substr(cmd.find(" ")+1);
 		if (cmd == "peers") {
-			auto res = p2p.getPeers();
-			for (auto r : res) std::cout << "  " << r.to_string() << std::endl;
+			auto res = p2p->getPeers();
+			for (auto r : res) std::cout << "  " << r->to_string() << std::endl;
 		}
 	}
 }
@@ -63,6 +63,8 @@ int main(int argc, const char **argv) {
 	argc--;
 	argv++;
 	
+	p2p = new P2P("ftl://cli");
+	
 	// Process Arguments
 	handle_options(&argv, &argc);
 	
@@ -79,6 +81,8 @@ int main(int argc, const char **argv) {
 	stop = true;
 	
 	nthread.join();
+	
+	delete p2p;
 	return 0;
 }
 
diff --git a/net/cpp/src/socket.cpp b/net/cpp/src/socket.cpp
index a992cf055..1f2f13641 100644
--- a/net/cpp/src/socket.cpp
+++ b/net/cpp/src/socket.cpp
@@ -1,8 +1,11 @@
 #define GLOG_NO_ABBREVIATED_SEVERITIES
 #include <glog/logging.h>
 
+#include <fcntl.h>
+
 #include <ftl/uri.hpp>
 #include <ftl/net/socket.hpp>
+#include <ftl/net/ws_internal.hpp>
 
 #ifndef WIN32
 #include <unistd.h>
@@ -28,6 +31,8 @@
 using namespace ftl;
 using ftl::net::Socket;
 using ftl::net::Protocol;
+using ftl::URI;
+using ftl::net::ws_connect;
 using namespace std;
 
 /*static std::string hexStr(const std::string &s)
@@ -119,10 +124,6 @@ static int tcpConnect(URI &uri) {
 	return csocket;
 }
 
-static int wsConnect(URI &uri) {
-	return 1;
-}
-
 Socket::Socket(int s) : sock_(s), pos_(0), proto_(nullptr) {
 	valid_ = true;
 	
@@ -151,12 +152,38 @@ Socket::Socket(const char *pUri) : pos_(0), uri_(pUri), proto_(nullptr) {
 	connected_ = false;
 	sock_ = INVALID_SOCKET;
 
+	scheme_ = uri.getProtocol();
 	if (uri.getProtocol() == URI::SCHEME_TCP) {
 		sock_ = tcpConnect(uri);
+		
+#ifdef WIN32
+		u_long on = 1;
+		ioctlsocket(sock_, FIONBIO, &on);
+#else
+		fcntl(sock_, F_SETFL, O_NONBLOCK);
+#endif
+		
 		valid_ = true;
 	} else if (uri.getProtocol() == URI::SCHEME_WS) {
-		wsConnect(uri);
-		LOG(ERROR) << "Websocket currently unsupported";
+		LOG(INFO) << "Websocket connect " << uri.getPath();
+		sock_ = tcpConnect(uri);
+		if (sock_ != INVALID_SOCKET) {
+			if (!ws_connect(sock_, uri)) {
+				LOG(ERROR) << "Websocket connection failed";
+				close();
+			}
+		} else {
+			LOG(ERROR) << "Connection refused to " << uri.getHost() << ":" << uri.getPort();
+		}
+		
+#ifdef WIN32
+		u_long on = 1;
+		ioctlsocket(sock_, FIONBIO, &on);
+#else
+		fcntl(sock_, F_SETFL, O_NONBLOCK);
+#endif
+
+		valid_ = true;
 	} else {
 		LOG(ERROR) << "Unrecognised connection protocol: " << pUri;
 	}
@@ -395,6 +422,20 @@ void Socket::_connected() {
 }
 
 int Socket::_send() {
+	// Are we using a websocket?
+	if (scheme_ == ftl::URI::SCHEME_WS) {
+		// Create a websocket header as well.
+		size_t len = 0;
+		char buf[20];  // TODO(nick) Should not be a stack buffer.
+		for (auto v : send_vec_) {
+			len += v.iov_len;
+		}
+		int rc = ws_prepare(wsheader_type::BINARY_FRAME, false, len, buf, 20);
+		if (rc == -1) return -1;
+		send_vec_[0].iov_base = buf;
+		send_vec_[0].iov_len = rc;
+	}
+	
 #ifdef WIN32
 	// TODO(nick) Use WSASend instead
 	int c = 0;
diff --git a/net/cpp/test/CMakeLists.txt b/net/cpp/test/CMakeLists.txt
index 03a789594..89a38738a 100644
--- a/net/cpp/test/CMakeLists.txt
+++ b/net/cpp/test/CMakeLists.txt
@@ -7,6 +7,7 @@ target_link_libraries(protocol_unit ${GLOG_LIBRARIES})
 
 add_executable(socket_unit
 	./tests.cpp
+	../src/ws_internal.cpp
 	./socket_unit.cpp
 )
 target_include_directories(socket_unit PUBLIC ${PROJECT_SOURCE_DIR}/include)
@@ -28,6 +29,7 @@ add_executable(p2p_base_unit
 	../src/protocol.cpp
 	../src/net.cpp
 	../src/listener.cpp
+	../src/ws_internal.cpp
 )
 target_include_directories(p2p_base_unit PUBLIC ${PROJECT_SOURCE_DIR}/include)
 target_link_libraries(p2p_base_unit ${URIPARSER_LIBRARIES} gflags ${GLOG_LIBRARIES} uuid)
@@ -40,6 +42,7 @@ add_executable(net_integration
 	../src/listener.cpp
 	../src/protocol.cpp
 	../src/net.cpp
+	../src/ws_internal.cpp
 )
 target_include_directories(net_integration PUBLIC ${PROJECT_SOURCE_DIR}/include)
 target_link_libraries(net_integration ${URIPARSER_LIBRARIES} ${GLOG_LIBRARIES})
-- 
GitLab