From f74f1f1a941c93ec997b4c8d2a4049be2b1f2463 Mon Sep 17 00:00:00 2001 From: Cloaked9000 Date: Tue, 20 Dec 2016 18:02:59 +0000 Subject: [PATCH] Bug fixes. Better syntax. SocketReactor actually calls callbacks. receive_all no longer tries to access out of bound array indexes. fr::Packet constructor can now take as many arguments as you like and they'll be added to it automatically. Added bool fr::Packet<< operator overload. --- include/frnetlib/Packet.h | 42 ++++++++++++++++++++++++++++++++ include/frnetlib/Socket.h | 4 +-- include/frnetlib/SocketReactor.h | 3 ++- include/frnetlib/TcpSocket.h | 4 +-- src/Socket.cpp | 16 ++++++------ src/SocketReactor.cpp | 11 +++++++-- src/TcpSocket.cpp | 10 ++++---- 7 files changed, 71 insertions(+), 19 deletions(-) diff --git a/include/frnetlib/Packet.h b/include/frnetlib/Packet.h index 5139a7d..69ec162 100644 --- a/include/frnetlib/Packet.h +++ b/include/frnetlib/Packet.h @@ -14,6 +14,28 @@ namespace fr class Packet { public: + Packet() noexcept = default; + + //Nasty constructor to allow things like Packet{1, 2, 3, "bob"}. + template + Packet(T const &part, Args &&...args) + { + add(part, std::forward(args)...); + } + + template + void add(T const& part, Args &&...args) + { + *this << part; + add(std::forward(args)...); + } + + template + void add(T const part) + { + *this << part; + } + /*! * Gets the data added to the packet * @@ -24,6 +46,26 @@ namespace fr return buffer; } + /* + * Adds a boolean variable to the packet + */ + inline Packet &operator<<(bool var) + { + buffer.resize(buffer.size() + sizeof(var)); + memcpy(&buffer[buffer.size() - sizeof(var)], &var, sizeof(var)); + return *this; + } + + /* + * Extracts a boolean variable from the packet + */ + inline Packet &operator>>(bool &var) + { + memcpy(&var, &buffer[0], sizeof(var)); + buffer.erase(0, sizeof(var)); + return *this; + } + /* * Adds a 16bit variable to the packet */ diff --git a/include/frnetlib/Socket.h b/include/frnetlib/Socket.h index bd12d1e..2cbdcf9 100644 --- a/include/frnetlib/Socket.h +++ b/include/frnetlib/Socket.h @@ -113,10 +113,10 @@ namespace fr * an error. * * @param dest Where to read the data into - * @param size The number of bytes to read + * @param buffer_size The number of bytes to read * @return Operation status. */ - Status receive_all(void *dest, size_t size); + Status receive_all(void *dest, size_t buffer_size); /*! * Checks to see if we're connected to a socket or not diff --git a/include/frnetlib/SocketReactor.h b/include/frnetlib/SocketReactor.h index 0419a36..e806a1e 100644 --- a/include/frnetlib/SocketReactor.h +++ b/include/frnetlib/SocketReactor.h @@ -16,6 +16,7 @@ namespace fr class SocketReactor { public: + SocketReactor() noexcept = default; SocketReactor(const SocketReactor&)=delete; SocketReactor(SocketReactor&&) noexcept = default; @@ -45,7 +46,7 @@ namespace fr bool wait(std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); private: - std::vector>> callbacks; + std::vector>> callbacks; fr::SocketSelector socket_selector; }; diff --git a/include/frnetlib/TcpSocket.h b/include/frnetlib/TcpSocket.h index 281ef64..f396ab7 100644 --- a/include/frnetlib/TcpSocket.h +++ b/include/frnetlib/TcpSocket.h @@ -61,11 +61,11 @@ public: * read in 'received'. * * @param data Where to store the received data. - * @param data_size The number of bytes to try and receive. Be sure that it's not larger than data. + * @param buffer_size The number of bytes to try and receive. Be sure that it's not larger than data. * @param received Will be filled with the number of bytes actually received, might be less than you requested. * @return The status of the operation, if the socket has disconnected etc. */ - virtual Status receive_raw(void *data, size_t data_size, size_t &received) override; + virtual Status receive_raw(void *data, size_t buffer_size, size_t &received) override; /*! * Sets the connections remote address. diff --git a/src/Socket.cpp b/src/Socket.cpp index 59e2986..24375ba 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -72,21 +72,23 @@ namespace fr return Socket::Status::Success; } - Socket::Status Socket::receive_all(void *dest, size_t size) + Socket::Status Socket::receive_all(void *dest, size_t buffer_size) { if(!is_connected) return Socket::Disconnected; + ssize_t bytes_remaining = buffer_size; size_t bytes_read = 0; - while(bytes_read < size) + while(bytes_remaining > 0) { - size_t read = 0; - Socket::Status status = receive_raw((uintptr_t*)dest + bytes_read, size, read); - if(status == Socket::Status::Success) - bytes_read += read; - else + size_t received = 0; + Status status = receive_raw((uintptr_t*)dest + bytes_read, (size_t)bytes_remaining, received); + if(status != fr::Socket::Success) return status; + bytes_remaining -= received; + bytes_read += received; } + return Socket::Status::Success; } diff --git a/src/SocketReactor.cpp b/src/SocketReactor.cpp index 0b44553..2a3e36a 100644 --- a/src/SocketReactor.cpp +++ b/src/SocketReactor.cpp @@ -2,6 +2,7 @@ // Created by fred on 20/12/16. // +#include #include "frnetlib/SocketReactor.h" namespace fr @@ -10,27 +11,33 @@ namespace fr void SocketReactor::add(const Socket &socket, std::function callback) { socket_selector.add(socket); + callbacks.emplace_back(std::make_pair(&socket, callback)); } void SocketReactor::remove(const Socket &socket) { socket_selector.remove(socket); + callbacks.erase(std::find_if(callbacks.begin(), callbacks.end(), [&](const std::pair> &check) { + return check.first->get_socket_descriptor() == socket.get_socket_descriptor(); + })); } bool SocketReactor::wait(std::chrono::milliseconds timeout) { + bool found = false; if(socket_selector.wait(timeout)) { //Find which socket sent the activity for(auto &callback : callbacks) { - if(socket_selector.is_ready(callback.first)) + if(socket_selector.is_ready(*callback.first)) { //Call the socket's callback callback.second(); + found = true; } } } - return false; + return found; } } \ No newline at end of file diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp index d7907c0..8cbf87a 100644 --- a/src/TcpSocket.cpp +++ b/src/TcpSocket.cpp @@ -52,10 +52,10 @@ namespace fr } } - Socket::Status TcpSocket::receive_raw(void *data, size_t data_size, size_t &received) + Socket::Status TcpSocket::receive_raw(void *data, size_t buffer_size, size_t &received) { received = 0; - if(unprocessed_buffer.size() < data_size) + if(unprocessed_buffer.size() < buffer_size) { //Read RECV_CHUNK_SIZE bytes into the recv buffer ssize_t status = ::recv(socket_descriptor, recv_buffer.get(), RECV_CHUNK_SIZE, 0); @@ -80,12 +80,12 @@ namespace fr return Socket::Status::Disconnected; } - if(received > data_size) - received = data_size; + if(received > buffer_size) + received = buffer_size; } else { - received = data_size; + received = buffer_size; } //Copy data to where it needs to go