merge resolved

This commit is contained in:
2019-06-11 15:56:13 +02:00
27 changed files with 5419 additions and 4660 deletions

View File

@ -3,9 +3,13 @@
#include <cstddef>
#include <cstdint>
#include <netdb.h>
#include <numeric>
#include <string>
namespace sls {
/* Base class for TCP socket, this is used to send data between detector, client
and receiver. Specific protocols inherit from this class.*/
class DataSocket {
public:
DataSocket(int socketId);
@ -13,14 +17,36 @@ class DataSocket {
virtual ~DataSocket();
DataSocket &operator=(DataSocket &&move) noexcept;
void swap(DataSocket &other) noexcept;
//No copy since the class manage the underlying socket
DataSocket(const DataSocket &) = delete;
DataSocket &operator=(DataSocket const &) = delete;
int getSocketId() const {
return socketId_;
int getSocketId() const { return socketId_; }
int Send(const void *buffer, size_t size);
template <typename T> int Send(T &&data) {
return Send(&data, sizeof(data));
}
int sendData(const void *buffer, size_t size);
int receiveData(void *buffer, size_t size);
// Variadic template to send all arguments
template <class... Args> int SendAll(Args &&... args) {
auto l = std::initializer_list<int>{Send(args)...};
auto sum = std::accumulate(begin(l), end(l), 0);
return sum;
}
int Receive(void *buffer, size_t size);
template <typename T> int Receive(T &arg) {
return Receive(&arg, sizeof(arg));
}
template <typename T> T Receive() {
T arg;
Receive(&arg, sizeof(arg));
return arg;
}
int read(void *buffer, size_t size);
int write(void *buffer, size_t size);
int setTimeOut(int t_seconds);
int setReceiveTimeout(int us);
void close();
@ -30,9 +56,4 @@ class DataSocket {
int socketId_ = -1;
};
int ConvertHostnameToInternetAddress(const char *const hostname, struct ::addrinfo **res);
int ConvertInternetAddresstoIpString(struct ::addrinfo *res, char *ip, const int ipsize);
struct ::sockaddr_in ConvertHostnameToInternetAddress(const std::string &hostname);
}; // namespace sls

View File

@ -13,16 +13,19 @@ class ServerInterface2 : public DataSocket {
using defs = slsDetectorDefs;
public:
ServerInterface2(int socketId) : DataSocket(socketId){}
ServerInterface2(int socketId) : DataSocket(socketId) {}
int sendResult(bool update, int ret, void *retval, int retvalSize,
char *mess = nullptr);
int receiveArg(int &ret, char *mess, void *arg, int sizeofArg);
int sendResult(int ret, void *retval, int retvalSize, char *mess = nullptr);
template <typename T> int sendResult(int ret, T &retval) {
return sendResult(ret, &retval, sizeof(retval, nullptr));
}
private:
template <typename T> int sendResult(T &&retval) {
Send(defs::OK);
Send(retval);
return defs::OK;
}
};
} // namespace sls

View File

@ -15,13 +15,13 @@ class ServerSocket : public DataSocket {
public:
ServerSocket(int port);
ServerInterface2 accept();
IpAddr getLastClient() noexcept { return lastClient; }
IpAddr getThisClient() noexcept { return thisClient; }
IpAddr getLockedBy() noexcept { return lockedBy; }
IpAddr getLastClient() const noexcept { return lastClient; }
IpAddr getThisClient() const noexcept { return thisClient; }
IpAddr getLockedBy() const noexcept { return lockedBy; }
bool differentClients() const noexcept {return lastClient != thisClient;}
void setLockedBy(IpAddr addr) { lockedBy = addr; }
void setLastClient(IpAddr addr) { lastClient = addr; }
int getPort() const;
void SendResult(int &ret, void *retval, int retvalSize, char *mess);
int getPort() const noexcept { return serverPort; }
private:
IpAddr thisClient;

View File

@ -1,6 +1,7 @@
#pragma once
#include <iostream>
#include <string>
#include <array>
namespace sls {
@ -15,6 +16,7 @@ class IpAddr {
IpAddr(const char *address);
std::string str() const;
std::string hex() const;
std::array<char, 16u> arr() const;
constexpr bool operator==(const IpAddr &other) const noexcept {
return addr_ == other.addr_;
}
@ -56,7 +58,7 @@ class MacAddr {
constexpr uint64_t uint64() const noexcept { return addr_; }
};
uint32_t HostnameToIp(const char *hostname);
IpAddr HostnameToIp(const char *hostname);
std::string IpToInterfaceName(const std::string& ip);
MacAddr InterfaceNameToMac(std::string inf);

View File

@ -1,10 +1,10 @@
/** API versions */
#define GITBRANCH "refgui"
#define APIMOENCH 0x181108
#define APILIB 0x190405
#define APIRECEIVER 0x190405
#define APILIB 0x190604
#define APIRECEIVER 0x190604
#define APIGUI 0x190405
#define APIGOTTHARD 0x190604
#define APIJUNGFRAU 0x190604
#define APIEIGER 0x190604
#define APICTB 0x190604
#define APIEIGER 0x190604
#define APIJUNGFRAU 0x190604
#define APIGOTTHARD 0x190604

View File

@ -62,34 +62,31 @@ int ClientSocket::sendCommandThenRead(int fnum, const void *args,
size_t args_size, void *retval,
size_t retval_size) {
int ret = slsDetectorDefs::FAIL;
sendData(&fnum, sizeof(fnum));
sendData(args, args_size);
Send(&fnum, sizeof(fnum));
Send(args, args_size);
readReply(ret, retval, retval_size);
return ret;
}
void ClientSocket::readReply(int &ret, void *retval, size_t retval_size) {
receiveData(&ret, sizeof(ret));
Receive(&ret, sizeof(ret));
if (ret == slsDetectorDefs::FAIL) {
char mess[MAX_STR_LENGTH]{};
// get error message
receiveData(mess, sizeof(mess));
FILE_LOG(logERROR) << socketType << " returned error: " << mess;
std::cout << "\n"; // needed to reset the color.
Receive(mess, sizeof(mess));
// Do we need to know hostname here?
// In that case save it???
if (socketType == "Receiver") {
throw ReceiverError(mess);
throw ReceiverError("Receiver returned: " + std::string(mess));
} else if (socketType == "Detector") {
throw DetectorError(mess);
throw DetectorError("Detector returned: " + std::string(mess));
} else {
throw GuiError(mess);
}
}
// get retval
receiveData(retval, retval_size);
Receive(retval, retval_size);
}
}; // namespace sls

View File

@ -3,13 +3,15 @@
#include "sls_detector_exceptions.h"
#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <netdb.h>
#include <sstream>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
namespace sls {
@ -25,7 +27,6 @@ DataSocket::~DataSocket() {
try {
close();
} catch (...) {
// pass
}
}
}
@ -40,18 +41,52 @@ DataSocket &DataSocket::operator=(DataSocket &&move) noexcept {
return *this;
}
int DataSocket::receiveData(void *buffer, size_t size) {
size_t dataRead = 0;
while (dataRead < size) {
dataRead +=
::read(getSocketId(), reinterpret_cast<char *>(buffer) + dataRead,
size - dataRead);
int DataSocket::Receive(void *buffer, size_t size) {
// TODO!(Erik) Add sleep? how many reties?
int bytes_expected = static_cast<int>(size); // signed size
int bytes_read = 0;
while (bytes_read < bytes_expected) {
auto this_read =
::read(getSocketId(), reinterpret_cast<char *>(buffer) + bytes_read,
bytes_expected - bytes_read);
if (this_read <= 0)
break;
bytes_read += this_read;
}
if (bytes_read == bytes_expected) {
return bytes_read;
} else {
std::ostringstream ss;
ss << "TCP socket read " << bytes_read << " bytes instead of "
<< bytes_expected << " bytes";
throw sls::SocketError(ss.str());
}
return dataRead;
}
int DataSocket::read(void *buffer, size_t size){
return ::read(getSocketId(), reinterpret_cast<char *>(buffer), size);
int DataSocket::Send(const void *buffer, size_t size) {
int bytes_sent = 0;
int data_size = static_cast<int>(size); // signed size
while (bytes_sent < (data_size)) {
auto this_send = ::write(getSocketId(), buffer, size);
if (this_send <= 0)
break;
bytes_sent += this_send;
}
if (bytes_sent != data_size) {
std::ostringstream ss;
ss << "TCP socket sent " << bytes_sent << " bytes instead of "
<< data_size << " bytes";
throw sls::SocketError(ss.str());
}
return bytes_sent;
}
int DataSocket::write(void *buffer, size_t size) {
return ::write(getSocketId(), buffer, size);
}
int DataSocket::read(void *buffer, size_t size) {
return ::read(getSocketId(), buffer, size);
}
int DataSocket::setReceiveTimeout(int us) {
@ -62,17 +97,6 @@ int DataSocket::setReceiveTimeout(int us) {
sizeof(struct timeval));
}
int DataSocket::sendData(const void *buffer, size_t size) {
int dataSent = 0;
while (dataSent < (int)size) {
dataSent +=
write(getSocketId(), reinterpret_cast<const char *>(buffer) + dataSent,
size - dataSent);
}
return dataSent;
}
int DataSocket::setTimeOut(int t_seconds) {
if (t_seconds <= 0)
return -1;
@ -102,7 +126,6 @@ void DataSocket::close() {
throw SocketError("could not close socket");
}
socketId_ = -1;
} else {
throw std::runtime_error("Socket ERROR: close called on bad socket\n");
}
@ -113,73 +136,4 @@ void DataSocket::shutDownSocket() {
close();
}
struct sockaddr_in
ConvertHostnameToInternetAddress(const std::string &hostname) {
struct addrinfo hints, *result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
struct sockaddr_in serverAddr {};
if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result) != 0) {
freeaddrinfo(result);
std::string msg = "ClientSocket cannot decode host:" + hostname + "\n";
throw SocketError(msg);
}
serverAddr.sin_family = AF_INET;
memcpy((char *)&serverAddr.sin_addr.s_addr,
&((struct sockaddr_in *)result->ai_addr)->sin_addr,
sizeof(in_addr_t));
freeaddrinfo(result);
return serverAddr;
}
int ConvertHostnameToInternetAddress(const char *const hostname,
struct ::addrinfo **res) {
// criteria in selecting socket address structures returned by res
struct ::addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
// get host info into res
int errcode = getaddrinfo(hostname, nullptr, &hints, res);
if (errcode != 0) {
FILE_LOG(logERROR) << "Could not convert hostname (" << hostname
<< ") to internet address (zmq):"
<< gai_strerror(errcode);
} else {
if (*res == nullptr) {
FILE_LOG(logERROR) << "Could not converthostname (" << hostname
<< ") to internet address (zmq):"
"gettaddrinfo returned null";
} else {
return 0;
}
}
FILE_LOG(logERROR) << "Could not convert hostname to internet address";
return 1;
};
/**
* Convert Internet Address structure pointer to ip string (char*)
* Clears the internet address structure as well
* @param res pointer to internet address structure
* @param ip pointer to char array to store result in
* @param ipsize size available in ip buffer
* @return 1 for fail, 0 for success
*/
// Do not make this static (for multi threading environment)
int ConvertInternetAddresstoIpString(struct ::addrinfo *res, char *ip,
const int ipsize) {
if (inet_ntop(res->ai_family,
&((struct sockaddr_in *)res->ai_addr)->sin_addr, ip,
ipsize) != nullptr) {
::freeaddrinfo(res);
return 0;
}
FILE_LOG(logERROR) << "Could not convert internet address to ip string";
return 1;
}
} // namespace sls

View File

@ -1,38 +1,24 @@
#include "ServerInterface2.h"
#include <cassert>
#include <cstring>
#include <sstream>
namespace sls {
int ServerInterface2::sendResult(bool update, int ret, void *retval,
int retvalSize, char *mess) {
int ServerInterface2::sendResult(int ret, void *retval, int retvalSize,
char *mess) {
// if (update && ret == defs::OK && server_->DifferentClients()) {
// ret = defs::FORCE_UPDATE;
// }
sendData(&ret, sizeof(ret));
write(&ret, sizeof(ret));
if (ret == defs::FAIL) {
// send error message
if (mess)
sendData(mess, MAX_STR_LENGTH);
// debugging feature. should not happen.
else
if (mess != nullptr) {
write(mess, MAX_STR_LENGTH);
} else {
FILE_LOG(logERROR) << "No error message provided for this "
"failure. Will mess up TCP\n";
}
} else {
write(retval, retvalSize);
}
sendData(retval, retvalSize);
return ret;
}
int ServerInterface2::receiveArg(int &ret, char *mess, void *arg,
int sizeofArg) {
assert(sizeofArg > 0);
int bytes_read = read(arg, sizeofArg);
if (bytes_read == sizeofArg) {
return defs::OK;
} else {
FILE_LOG(logERROR) << "Read: " << bytes_read << " instead of "
<< sizeofArg;
return defs::FAIL;
}
}
} // namespace sls

View File

@ -52,26 +52,4 @@ ServerInterface2 ServerSocket::accept() {
return ServerInterface2(newSocket);
}
int ServerSocket::getPort() const { return serverPort; }
void ServerSocket::SendResult(int &ret, void* retval, int retvalSize, char* mess) {
// send success of operation
sendData(&ret, sizeof(ret));
if (ret == slsDetectorDefs::FAIL) {
// create error message if empty
if (!strlen(mess)) {
strcpy(mess, "No error message provided for this failure in server. Will mess up TCP.");
}
sendData(mess, MAX_STR_LENGTH);
throw sls::RuntimeError(mess);
}
// send return value
sendData(retval, retvalSize);
}
}; // namespace sls

View File

@ -27,10 +27,15 @@ IpAddr::IpAddr(const std::string &address) {
IpAddr::IpAddr(const char *address) { inet_pton(AF_INET, address, &addr_); }
std::string IpAddr::str() const {
char ipstring[INET_ADDRSTRLEN]{};
inet_ntop(AF_INET, &addr_, ipstring, INET_ADDRSTRLEN);
return arr().data();
}
std::array<char, INET_ADDRSTRLEN> IpAddr::arr() const{
std::array<char, INET_ADDRSTRLEN> ipstring{};
inet_ntop(AF_INET, &addr_, ipstring.data(), INET_ADDRSTRLEN);
return ipstring;
}
std::string IpAddr::hex() const {
std::ostringstream ss;
ss << std::hex << std::setfill('0');
@ -75,7 +80,7 @@ std::ostream &operator<<(std::ostream &out, const MacAddr &addr) {
return out << addr.str();
}
uint32_t HostnameToIp(const char *hostname) {
IpAddr HostnameToIp(const char *hostname) {
addrinfo hints;
addrinfo *result = nullptr;
memset(&hints, 0, sizeof(hints));
@ -87,7 +92,7 @@ uint32_t HostnameToIp(const char *hostname) {
}
uint32_t ip = ((sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
return ip;
return IpAddr(ip);
}
std::string IpToInterfaceName(const std::string &ip) {

View File

@ -10,14 +10,14 @@ std::vector<char> server() {
auto server = sls::ServerSocket(1950);
auto s = server.accept();
std::vector<char> buffer(100, '\0');
s.receiveData(buffer.data(), buffer.size());
s.Receive(buffer.data(), buffer.size());
std::cout << "ServerReceived: " << std::string(buffer.begin(), buffer.end())
<< '\n';
std::vector<char> to_send(100, '\0');
to_send[0] = 'O';
to_send[1] = 'K';
s.sendData(to_send.data(), to_send.size());
s.Send(to_send.data(), to_send.size());
s.close();
return buffer;
}
@ -31,8 +31,8 @@ TEST_CASE("The server recive the same message as we send", "[support]") {
auto s = std::async(std::launch::async, server);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto client = sls::DetectorSocket("localhost", 1950);
client.sendData(sent_message.data(), sent_message.size());
client.receiveData(received_message.data(), received_message.size());
client.Send(sent_message.data(), sent_message.size());
client.Receive(received_message.data(), received_message.size());
client.close();
auto server_message = s.get();

View File

@ -11,9 +11,11 @@ using namespace sls;
TEST_CASE("Convert mac address using classes", "[support]") {
std::vector<uint64_t> vec_addr{346856806822, 346856806852, 262027939863028,0, 281474976710655};
std::vector<uint64_t> vec_addr{346856806822, 346856806852, 262027939863028,
0, 281474976710655};
std::vector<std::string> vec_ans{"00:50:c2:46:d9:a6", "00:50:c2:46:d9:c4",
"ee:50:22:46:d9:f4", "00:00:00:00:00:00", "ff:ff:ff:ff:ff:ff"};
"ee:50:22:46:d9:f4", "00:00:00:00:00:00",
"ff:ff:ff:ff:ff:ff"};
for (size_t i = 0; i != vec_addr.size(); ++i) {
auto mac0 = MacAddr(vec_addr[i]);
auto mac1 = MacAddr(vec_ans[i]);
@ -42,12 +44,13 @@ TEST_CASE("Hex representation of MAC", "[support]") {
}
TEST_CASE("Convert IP using classes ", "[support]") {
std::vector<uint32_t> vec_addr{4073554305, 2747957633, 2697625985, 2566979594, 0};
std::vector<uint32_t> vec_addr{4073554305, 2747957633, 2697625985,
2566979594, 0};
std::vector<std::string> vec_ans{"129.129.205.242", "129.129.202.163",
"129.129.202.160", "10.0.1.153", "0.0.0.0"};
std::vector<std::string> vec_hex{"8181cdf2", "8181caa3",
"8181caa0", "0a000199","00000000"};
"129.129.202.160", "10.0.1.153",
"0.0.0.0"};
std::vector<std::string> vec_hex{"8181cdf2", "8181caa3", "8181caa0",
"0a000199", "00000000"};
for (size_t i = 0; i != vec_addr.size(); ++i) {
auto ip0 = IpAddr(vec_addr[i]);
@ -59,7 +62,9 @@ TEST_CASE("Convert IP using classes ", "[support]") {
CHECK(ip0 == vec_ans[i]);
CHECK(ip1 == vec_ans[i]);
CHECK(ip0.str() == vec_ans[i]);
CHECK(ip0.arr().data() == vec_ans[i]);
CHECK(ip1.str() == vec_ans[i]);
CHECK(ip1.arr().data() == vec_ans[i]);
CHECK(ip0.hex() == vec_hex[i]);
CHECK(ip1.hex() == vec_hex[i]);
}
@ -80,7 +85,7 @@ TEST_CASE("Convert to uint for sending over network", "[support]") {
CHECK(b == 4073554305);
}
TEST_CASE("Hostname lookup failed throws", "[support]"){
TEST_CASE("Hostname lookup failed throws", "[support]") {
CHECK_THROWS_AS(HostnameToIp("pippifax"), RuntimeError);
}
@ -90,7 +95,6 @@ TEST_CASE("IP Output operator gives same result as string", "[support]") {
os << addr;
CHECK(os.str() == "129.129.205.242");
CHECK(os.str() == addr.str());
}
TEST_CASE("MAC Output operator gives same result as string", "[support]") {
@ -101,4 +105,4 @@ TEST_CASE("MAC Output operator gives same result as string", "[support]") {
CHECK(os.str() == addr.str());
}
//TODO!(Erik) Look up a real hostname and verify the IP
// TODO!(Erik) Look up a real hostname and verify the IP