blob: 00b6ac9c040704d3215c5785dc005a2ad3570acd [file] [log] [blame]
/*
* Socket.h
*
* Created on: 05.02.2018
* Author: psota
*/
#ifndef BASYX_ABSTRACTION_NET_SOCKET_H
#define BASYX_ABSTRACTION_NET_SOCKET_H
#include <BaSyx/abstraction/impl/socket_impl.h>
#include <BaSyx/util/util.h>
#include <BaSyx/log/log.h>
#include <string>
namespace basyx {
namespace net {
namespace tcp {
template <typename socket_impl>
class basic_socket {
private:
basyx::log log;
std::unique_ptr<socket_impl> socket;
basic_socket<socket_impl>& _move_socket(basic_socket<socket_impl>&& other)
{
// close current socket and assign new one
if (this->socket != nullptr)
this->socket->close();
this->socket = std::move(other.socket);
// other no longer represents a socket connection
other.socket.reset(nullptr);
return *this;
}
public:
basic_socket()
: socket { nullptr }
, log { "Socket" } {};
basic_socket(std::unique_ptr<socket_impl> socket)
: socket { std::forward<std::unique_ptr<socket_impl>>(socket) }
, log { "Socket" } {};
~basic_socket() {};
// Delete copy-assignment and constructor, there should only ever be one Socket object representing a single connection
basic_socket<socket_impl>& operator=(basic_socket<socket_impl>& other) = delete;
basic_socket(basic_socket<socket_impl>& other) = delete;
// Allow move-operations
basic_socket<socket_impl>& operator=(basic_socket<socket_impl>&& other) { return _move_socket(std::forward<basic_socket<socket_impl>>(other)); };
basic_socket(basic_socket<socket_impl>&& other) { _move_socket(std::forward<basic_socket<socket_impl>>(other)); };
template <typename Buffer>
std::size_t Send(Buffer&& buffer)
{
if (socket == nullptr)
return 0;
return socket->write(buffer.data(), buffer.size());
}
template <typename MutableBuffer>
std::size_t Receive(MutableBuffer&& buffer)
{
if (socket == nullptr)
return 0;
return socket->recv(buffer.data(), buffer.size(), 0);
}
static basic_socket<socket_impl> Connect(const std::string& address, int port)
{
return basic_socket<socket_impl>::Connect(address, std::to_string(port));
}
static basic_socket<socket_impl> Connect(const std::string& address, const std::string& port)
{
//ToDo: Error handling
auto sock_impl = util::make_unique<socket_impl>();
auto result = sock_impl->connect(address, port);
if (result != 0)
return basic_socket<socket_impl> {};
return basic_socket<socket_impl> { std::forward<std::unique_ptr<socket_impl>>(sock_impl) };
}
int GetErrorCode()
{
if (this->socket == nullptr)
return -1;
return this->socket->getErrorCode();
}
void Close()
{
if (this->socket != nullptr) {
log.trace("Closing socket...");
//this->socket->shutdown(SHUTDOWN_RDWR);
this->socket->close();
this->socket.reset();
}
}
bool Healthy()
{
if (this->socket == nullptr)
return false;
return true;
}
};
using Socket = basic_socket<basyx::net::impl::socket_impl>;
};
}
}
#endif /* BASYX_ABSTRACTION_NET_SOCKET_H */