From 99a1c609f1fc5c856de41f782f4dcd624243ed4f Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 23 Jan 2019 11:47:13 +0100 Subject: [PATCH] starting to add new Socket interface --- .../slsDetector/slsDetector.cpp | 30 ++++-------- slsSupportLib/CMakeLists.txt | 6 +++ slsSupportLib/include/ClientSocket.h | 17 +++++++ slsSupportLib/include/DataSocket.h | 23 ++++++++++ slsSupportLib/include/ServerSocket.h | 25 ++++++++++ slsSupportLib/src/ClientSocket.cpp | 35 ++++++++++++++ slsSupportLib/src/DataSocket.cpp | 38 +++++++++++++++ slsSupportLib/src/ServerSocket.cpp | 46 +++++++++++++++++++ slsSupportLib/tests/CMakeLists.txt | 1 + slsSupportLib/tests/test-ClientInterface.cpp | 12 +++++ 10 files changed, 212 insertions(+), 21 deletions(-) create mode 100644 slsSupportLib/include/ClientSocket.h create mode 100644 slsSupportLib/include/DataSocket.h create mode 100644 slsSupportLib/include/ServerSocket.h create mode 100644 slsSupportLib/src/ClientSocket.cpp create mode 100644 slsSupportLib/src/DataSocket.cpp create mode 100644 slsSupportLib/src/ServerSocket.cpp create mode 100644 slsSupportLib/tests/test-ClientInterface.cpp diff --git a/slsDetectorSoftware/slsDetector/slsDetector.cpp b/slsDetectorSoftware/slsDetector/slsDetector.cpp index b3fd44e0f..d088de3fd 100644 --- a/slsDetectorSoftware/slsDetector/slsDetector.cpp +++ b/slsDetectorSoftware/slsDetector/slsDetector.cpp @@ -1,5 +1,6 @@ #include "slsDetector.h" #include "ClientInterface.h" +#include "ClientSocket.h" #include "MySocketTCP.h" #include "SharedMemory.h" #include "file_utils.h" @@ -736,30 +737,17 @@ slsDetectorDefs::detectorType slsDetector::getDetectorTypeAsEnum(const std::stri int fnum = F_GET_DETECTOR_TYPE; int ret = FAIL; detectorType retval = GENERIC; - MySocketTCP *mySocket = nullptr; - - try { - mySocket = new MySocketTCP(hostname.c_str(), cport); - } catch (...) { - FILE_LOG(logERROR) << "Cannot create socket to control server " << hostname - << " over port " << cport; - return retval; - } - FILE_LOG(logDEBUG1) << "Getting detector type "; - if (mySocket->Connect() >= 0) { - mySocket->SendDataOnly(&fnum, sizeof(fnum)); - mySocket->ReceiveDataOnly(&ret, sizeof(ret)); - mySocket->ReceiveDataOnly(&retval, sizeof(retval)); - mySocket->Disconnect(); - } else { + try{ + sls::ClientSocket cs(hostname, cport); + cs.sendData(reinterpret_cast(&fnum), sizeof(fnum)); + cs.receiveData(reinterpret_cast(&ret), sizeof(ret)); + cs.receiveData(reinterpret_cast(&retval), sizeof(retval)); + }catch(...){ + //TODO! (Erik) Do not swallow exception but let the caller handle it FILE_LOG(logERROR) << "Cannot connect to server " << hostname << " over port " << cport; } - if (ret != FAIL) { - FILE_LOG(logDEBUG1) << "Detector type is " << retval; - } - - delete mySocket; + FILE_LOG(logDEBUG1) << "Detector type is " << retval; return retval; } diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index 01f815ed1..d495d381f 100644 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -3,6 +3,9 @@ set(SOURCES src/CmdLineParser.cpp src/string_utils.cpp src/file_utils.cpp + src/ClientSocket.cpp + src/DataSocket.cpp + src/ServerSocket.cpp ) set(HEADERS @@ -22,6 +25,9 @@ set(PUBLICHEADERS include/MySocketTCP.h include/genericSocket.h include/logger.h + include/ClientSocket.h + include/DataSocket.h + include/ServerSocket.h ) add_library(slsSupportLib SHARED diff --git a/slsSupportLib/include/ClientSocket.h b/slsSupportLib/include/ClientSocket.h new file mode 100644 index 000000000..765647151 --- /dev/null +++ b/slsSupportLib/include/ClientSocket.h @@ -0,0 +1,17 @@ +#pragma once +#include "DataSocket.h" +#include +#include +#include +#include + +namespace sls{ + +class ClientSocket: public DataSocket{ +public: + ClientSocket(const std::string& hostname, uint16_t port_number); +private: + +}; + +}; //namespace sls \ No newline at end of file diff --git a/slsSupportLib/include/DataSocket.h b/slsSupportLib/include/DataSocket.h new file mode 100644 index 000000000..948dd225a --- /dev/null +++ b/slsSupportLib/include/DataSocket.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +namespace sls { + +class DataSocket { + public: + DataSocket(int socketId); + + int getSocketId() const{ + return socketId_; + } + size_t sendData(char *buffer, size_t size); + size_t receiveData(char * buffer, size_t size); + + void close(); + + private: + int socketId_ = -1; +}; + +}; // namespace sls diff --git a/slsSupportLib/include/ServerSocket.h b/slsSupportLib/include/ServerSocket.h new file mode 100644 index 000000000..00a3536d0 --- /dev/null +++ b/slsSupportLib/include/ServerSocket.h @@ -0,0 +1,25 @@ +#pragma once + +#include "DataSocket.h" + +#include +#include +#include +#include +#include + +namespace sls { + +class ServerSocket : public DataSocket { + public: + ServerSocket(int port); + DataSocket accept(); + const std::string &getLastClient() { return lastClient_; } + + private: + std::string lastClient_ = std::string(INET_ADDRSTRLEN, '\0'); + std::string thisClient_ = std::string(INET_ADDRSTRLEN, '\0'); + // char lastClient_[INET_ADDRSTRLEN]{}; +}; + +}; //namespace sls \ No newline at end of file diff --git a/slsSupportLib/src/ClientSocket.cpp b/slsSupportLib/src/ClientSocket.cpp new file mode 100644 index 000000000..329c6a7ea --- /dev/null +++ b/slsSupportLib/src/ClientSocket.cpp @@ -0,0 +1,35 @@ +#include "ClientSocket.h" +#include +#include +#include +#include + +namespace sls { + +ClientSocket::ClientSocket(const std::string &host, uint16_t port) : DataSocket(socket(AF_INET, SOCK_STREAM, 0)) { + + struct addrinfo hints, *result; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + + if (getaddrinfo(host.c_str(), NULL, &hints, &result) != 0) { + throw std::runtime_error("ClientSocket ERROR: cannot decode host\n"); + } + + //TODO! Erik, results could have multiple entries do we need to loop through them? + struct sockaddr_in serverAddr {}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); + memcpy((char *)&serverAddr.sin_addr.s_addr, + &((struct sockaddr_in *)result->ai_addr)->sin_addr, sizeof(in_addr_t)); + + if (connect(getSocketId(), (struct sockaddr *)&serverAddr, sizeof(serverAddr)) != 0){ + freeaddrinfo(result); + throw std::runtime_error("ClientSocket ERROR: cannot connect to host\n"); + } + freeaddrinfo(result); +} + +}; //namespace sls \ No newline at end of file diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp new file mode 100644 index 000000000..63cf5774c --- /dev/null +++ b/slsSupportLib/src/DataSocket.cpp @@ -0,0 +1,38 @@ + +#include "DataSocket.h" +#include +#include +#include +#include + +namespace sls { + +DataSocket::DataSocket(int socketId) : socketId_(socketId) {} + +size_t DataSocket::receiveData(char *buffer, size_t size) { + std::cout << "Sending\n"; + size_t dataRead = 0; + while (dataRead < size) { + dataRead += read(getSocketId(), buffer + dataRead, size - dataRead); + } + return dataRead; +} + +size_t DataSocket::sendData(char *buffer, size_t size) { + std::cout << "Receiving\n"; + size_t dataSent = 0; + while (dataSent < size) { + dataSent += write(getSocketId(), buffer + dataSent, size - dataSent); + } + return dataSent; +} + +void DataSocket::close() { + if (socketId_ > 0) { + ::close(socketId_); + } else { + throw std::runtime_error("Socket ERROR: close called on bad socket\n"); + } +} + +} // namespace sls diff --git a/slsSupportLib/src/ServerSocket.cpp b/slsSupportLib/src/ServerSocket.cpp new file mode 100644 index 000000000..0f71dcaa7 --- /dev/null +++ b/slsSupportLib/src/ServerSocket.cpp @@ -0,0 +1,46 @@ +#include "ServerSocket.h" +#include "DataSocket.h" +#include +#include +#include +#define DEFAULT_PACKET_SIZE 1286 +#define SOCKET_BUFFER_SIZE (100 * 1024 * 1024) //100 MB +#define DEFAULT_BACKLOG 5 + +namespace sls { + +ServerSocket::ServerSocket(int port) : DataSocket(socket(AF_INET, SOCK_STREAM, 0)) { + + std::cout << "Server constructed\n"; + + struct sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(getSocketId(), (struct sockaddr *)&serverAddr, sizeof(serverAddr)) != 0) { + close(); + throw std::runtime_error("Server ERROR: cannot bind socket"); + } + if (listen(getSocketId(), DEFAULT_BACKLOG) != 0) { + close(); + throw std::runtime_error("Server ERROR: cannot listen to socket"); + } +} + +DataSocket ServerSocket::accept() { + struct sockaddr_in clientAddr; + socklen_t addr_size = sizeof clientAddr; + int newSocket = ::accept(getSocketId(), (struct sockaddr *)&clientAddr, &addr_size); + if (newSocket == -1) { + throw std::runtime_error("Server ERROR: socket accept failed\n"); + } + inet_ntop(AF_INET, &(clientAddr.sin_addr), &thisClient_.front(), INET_ADDRSTRLEN); + std::cout << "lastClient: " << lastClient_ << " thisClient: " << thisClient_ << '\n'; + //Here goes any check for locks etc + lastClient_ = thisClient_; + + return DataSocket(newSocket); +} + +}; //namespace sls \ No newline at end of file diff --git a/slsSupportLib/tests/CMakeLists.txt b/slsSupportLib/tests/CMakeLists.txt index fb0739650..f46e60a68 100644 --- a/slsSupportLib/tests/CMakeLists.txt +++ b/slsSupportLib/tests/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories( set(SOURCES test.cpp + test-ClientInterface.cpp test-CmdLineParser.cpp test-container_utils.cpp test-string_utils.cpp diff --git a/slsSupportLib/tests/test-ClientInterface.cpp b/slsSupportLib/tests/test-ClientInterface.cpp new file mode 100644 index 000000000..633e8a0f9 --- /dev/null +++ b/slsSupportLib/tests/test-ClientInterface.cpp @@ -0,0 +1,12 @@ +#include "ClientInterface.h" +#include "MySocketTCP.h" +#include "catch.hpp" + +//tests to add +//help for all docs +//command for all depreciated commands + +TEST_CASE("hopp") { + REQUIRE(true); + +} \ No newline at end of file