Skip to content
Snippets Groups Projects
Commit 750a785a authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Add read/write functions for basic types to the language

Also checks that server socket is not accessed by the server itself
parent 78758f35
No related branches found
No related tags found
1 merge request!126Begin socket handling: core functionalities are available
......@@ -11,7 +11,7 @@ SocketModule::SocketModule()
std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const Socket>(const uint64_t&)>>(
[](const uint64_t& port_number) -> std::shared_ptr<const Socket> {
return std::make_shared<const Socket>(createSocketServer(port_number));
return std::make_shared<const Socket>(createServerSocket(port_number));
}
));
......@@ -21,7 +21,7 @@ SocketModule::SocketModule()
BuiltinFunctionEmbedder<std::shared_ptr<const Socket>(std::shared_ptr<const Socket>)>>(
[](std::shared_ptr<const Socket> server_socket) -> std::shared_ptr<const Socket> {
return std::make_shared<const Socket>(acceptSocketClient(*server_socket));
return std::make_shared<const Socket>(acceptClientSocket(*server_socket));
}
));
......@@ -32,7 +32,246 @@ SocketModule::SocketModule()
[](const std::string& hostname,
const uint64_t& port_number) -> std::shared_ptr<const Socket> {
return std::make_shared<const Socket>(connectSocketServer(hostname, port_number));
return std::make_shared<const Socket>(connectServerSocket(hostname, port_number));
}
));
this->_addBuiltinFunction("write",
std::make_shared<
BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const bool&)>>(
[](const std::shared_ptr<const Socket>& socket, const bool& value) -> void {
write(*socket, value);
}
));
this->_addBuiltinFunction("write",
std::make_shared<
BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const uint64_t&)>>(
[](const std::shared_ptr<const Socket>& socket, const uint64_t& value) -> void {
write(*socket, value);
}
));
this->_addBuiltinFunction("write",
std::make_shared<
BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const int64_t&)>>(
[](const std::shared_ptr<const Socket>& socket, const int64_t& value) -> void {
write(*socket, value);
}
));
this->_addBuiltinFunction("write",
std::make_shared<
BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const double&)>>(
[](const std::shared_ptr<const Socket>& socket, const double& value) -> void {
write(*socket, value);
}
));
this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
const TinyVector<1>&)>>(
[](const std::shared_ptr<const Socket>& socket,
const TinyVector<1>& value) -> void { write(*socket, value); }
));
this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
const TinyVector<2>&)>>(
[](const std::shared_ptr<const Socket>& socket,
const TinyVector<2>& value) -> void { write(*socket, value); }
));
this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
const TinyVector<3>&)>>(
[](const std::shared_ptr<const Socket>& socket,
const TinyVector<3>& value) -> void { write(*socket, value); }
));
this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
const TinyMatrix<1>&)>>(
[](const std::shared_ptr<const Socket>& socket,
const TinyMatrix<1>& value) -> void { write(*socket, value); }
));
this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
const TinyMatrix<2>&)>>(
[](const std::shared_ptr<const Socket>& socket,
const TinyMatrix<2>& value) -> void { write(*socket, value); }
));
this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
const TinyMatrix<3>&)>>(
[](const std::shared_ptr<const Socket>& socket,
const TinyMatrix<3>& value) -> void { write(*socket, value); }
));
this->_addBuiltinFunction("write",
std::make_shared<
BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const std::string&)>>(
[](const std::shared_ptr<const Socket>& socket, const std::string& value) -> void {
write(*socket, value.size());
write(*socket, value);
}
));
this->_addBuiltinFunction("read_B",
std::make_shared<BuiltinFunctionEmbedder<bool(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> bool {
bool value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_N",
std::make_shared<BuiltinFunctionEmbedder<uint64_t(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> uint64_t {
uint64_t value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_Z",
std::make_shared<BuiltinFunctionEmbedder<int64_t(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> int64_t {
int64_t value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R",
std::make_shared<BuiltinFunctionEmbedder<double(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> double {
double value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R1", std::make_shared<
BuiltinFunctionEmbedder<TinyVector<1>(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> TinyVector<1> {
TinyVector<1> value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R2", std::make_shared<
BuiltinFunctionEmbedder<TinyVector<2>(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> TinyVector<2> {
TinyVector<2> value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R3", std::make_shared<
BuiltinFunctionEmbedder<TinyVector<3>(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> TinyVector<3> {
TinyVector<3> value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R1x1",
std::make_shared<
BuiltinFunctionEmbedder<TinyMatrix<1>(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<1> {
TinyMatrix<1> value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R2x2",
std::make_shared<
BuiltinFunctionEmbedder<TinyMatrix<2>(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<2> {
TinyMatrix<2> value;
read(*socket, value);
return value;
}
));
this->_addBuiltinFunction("read_R3x3",
std::make_shared<
BuiltinFunctionEmbedder<TinyMatrix<3>(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<3> {
TinyMatrix<3> value;
read(*socket, value);
return value;
}
));
this
->_addBuiltinFunction("read_string",
std::make_shared<BuiltinFunctionEmbedder<std::string(const std::shared_ptr<const Socket>&)>>(
[](const std::shared_ptr<const Socket>& socket) -> std::string {
size_t size;
read(*socket, size);
std::string value;
if (size > 0) {
value.resize(size);
read(*socket, value);
}
return value;
}
));
......
......@@ -16,10 +16,12 @@ class Socket::Internals
int m_socket_fd;
sockaddr_in m_address;
const bool m_is_server_socket;
public:
friend Socket createSocketServer(int port_number);
friend Socket acceptSocketClient(const Socket& server);
friend Socket connectSocketServer(const std::string& server_name, int port_number);
friend Socket createServerSocket(int port_number);
friend Socket acceptClientSocket(const Socket& server);
friend Socket connectServerSocket(const std::string& server_name, int port_number);
friend std::ostream&
operator<<(std::ostream& os, const Socket::Internals& internals)
......@@ -45,6 +47,12 @@ class Socket::Internals
return os;
}
bool
isServerSocket() const
{
return m_is_server_socket;
}
int
fileDescriptor() const
{
......@@ -54,7 +62,7 @@ class Socket::Internals
Internals(const Internals&) = delete;
Internals(Internals&&) = delete;
Internals() = default;
Internals(bool is_server_socket = false) : m_is_server_socket{is_server_socket} {}
~Internals()
{
......@@ -69,9 +77,9 @@ operator<<(std::ostream& os, const Socket& socket)
}
Socket
createSocketServer(int port_number)
createServerSocket(int port_number)
{
auto p_socket_internals = std::make_shared<Socket::Internals>();
auto p_socket_internals = std::make_shared<Socket::Internals>(true);
Socket::Internals& socket_internals = *p_socket_internals;
socket_internals.m_socket_fd = ::socket(AF_INET, SOCK_STREAM, 0);
......@@ -97,7 +105,7 @@ createSocketServer(int port_number)
}
Socket
acceptSocketClient(const Socket& server)
acceptClientSocket(const Socket& server)
{
auto p_socket_internals = std::make_shared<Socket::Internals>();
Socket::Internals& socket_internals = *p_socket_internals;
......@@ -119,7 +127,7 @@ acceptSocketClient(const Socket& server)
}
Socket
connectSocketServer(const std::string& server_name, int port_number)
connectServerSocket(const std::string& server_name, int port_number)
{
std::cout << "Trying to establish connection to " << server_name << ':' << port_number << '\n';
......@@ -158,6 +166,10 @@ connectSocketServer(const std::string& server_name, int port_number)
void
Socket::_write(const char* data, const size_t lenght) const
{
if (this->m_internals->isServerSocket()) {
throw NormalError("Server cannot write to server socket!");
}
if (::write(this->m_internals->fileDescriptor(), data, lenght) < 0) {
throw NormalError(strerror(errno));
}
......@@ -166,11 +178,15 @@ Socket::_write(const char* data, const size_t lenght) const
void
Socket::_read(char* data, const size_t length) const
{
if (this->m_internals->isServerSocket()) {
throw NormalError("Server cannot read from server socket!");
}
size_t received = 0;
do {
int n = ::read(this->m_internals->fileDescriptor(), reinterpret_cast<char*>(data) + received, length - received);
if (n <= 0) {
throw NormalError(strerror(errno));
throw NormalError("Could not read data");
}
received += n;
} while (received < length);
......
......@@ -4,6 +4,7 @@
#include <memory>
#include <string>
#include <type_traits>
#include <utils/PugsTraits.hpp>
class Socket
{
......@@ -20,9 +21,9 @@ class Socket
public:
friend std::ostream& operator<<(std::ostream& os, const Socket& s);
friend Socket createSocketServer(int port_number);
friend Socket acceptSocketClient(const Socket& server);
friend Socket connectSocketServer(const std::string& server_name, int port_number);
friend Socket createServerSocket(int port_number);
friend Socket acceptClientSocket(const Socket& server);
friend Socket connectServerSocket(const std::string& server_name, int port_number);
template <typename T>
friend void write(const Socket& socket, const T& value);
......@@ -42,14 +43,15 @@ class Socket
~Socket() = default;
};
Socket createSocketServer(int port_number);
Socket acceptSocketClient(const Socket& server);
Socket connectSocketServer(const std::string& server_name, int port_number);
Socket createServerSocket(int port_number);
Socket acceptClientSocket(const Socket& server);
Socket connectServerSocket(const std::string& server_name, int port_number);
template <typename T>
inline void
write(const Socket& socket, const T& value)
{
static_assert(std::is_arithmetic_v<T> or is_tiny_vector_v<T> or is_tiny_matrix_v<T>, "unexpected value type");
socket._write(reinterpret_cast<const char*>(&value), sizeof(T) / sizeof(char));
}
......@@ -73,6 +75,7 @@ void
read(const Socket& socket, ArrayT<T, R...>& array)
{
static_assert(not std::is_const_v<T>, "cannot read values into const data");
static_assert(std::is_arithmetic_v<T> or is_tiny_vector_v<T> or is_tiny_matrix_v<T>, "unexpected value type");
socket._read(reinterpret_cast<char*>(&array[0]), array.size() * sizeof(T) / sizeof(char));
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment