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.
This commit is contained in:
Cloaked9000 2016-12-20 18:02:59 +00:00
parent 70779fbe9c
commit f74f1f1a94
7 changed files with 71 additions and 19 deletions

View File

@ -14,6 +14,28 @@ namespace fr
class Packet class Packet
{ {
public: public:
Packet() noexcept = default;
//Nasty constructor to allow things like Packet{1, 2, 3, "bob"}.
template <typename T, typename ...Args>
Packet(T const &part, Args &&...args)
{
add(part, std::forward<Args>(args)...);
}
template<typename T, typename ...Args>
void add(T const& part, Args &&...args)
{
*this << part;
add(std::forward<Args>(args)...);
}
template<typename T>
void add(T const part)
{
*this << part;
}
/*! /*!
* Gets the data added to the packet * Gets the data added to the packet
* *
@ -24,6 +46,26 @@ namespace fr
return buffer; 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 * Adds a 16bit variable to the packet
*/ */

View File

@ -113,10 +113,10 @@ namespace fr
* an error. * an error.
* *
* @param dest Where to read the data into * @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. * @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 * Checks to see if we're connected to a socket or not

View File

@ -16,6 +16,7 @@ namespace fr
class SocketReactor class SocketReactor
{ {
public: public:
SocketReactor() noexcept = default;
SocketReactor(const SocketReactor&)=delete; SocketReactor(const SocketReactor&)=delete;
SocketReactor(SocketReactor&&) noexcept = default; SocketReactor(SocketReactor&&) noexcept = default;
@ -45,7 +46,7 @@ namespace fr
bool wait(std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); bool wait(std::chrono::milliseconds timeout = std::chrono::milliseconds(0));
private: private:
std::vector<std::pair<fr::Socket&, std::function<void()>>> callbacks; std::vector<std::pair<const fr::Socket*, std::function<void()>>> callbacks;
fr::SocketSelector socket_selector; fr::SocketSelector socket_selector;
}; };

View File

@ -61,11 +61,11 @@ public:
* read in 'received'. * read in 'received'.
* *
* @param data Where to store the received data. * @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. * @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. * @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. * Sets the connections remote address.

View File

@ -72,21 +72,23 @@ namespace fr
return Socket::Status::Success; 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) if(!is_connected)
return Socket::Disconnected; return Socket::Disconnected;
ssize_t bytes_remaining = buffer_size;
size_t bytes_read = 0; size_t bytes_read = 0;
while(bytes_read < size) while(bytes_remaining > 0)
{ {
size_t read = 0; size_t received = 0;
Socket::Status status = receive_raw((uintptr_t*)dest + bytes_read, size, read); Status status = receive_raw((uintptr_t*)dest + bytes_read, (size_t)bytes_remaining, received);
if(status == Socket::Status::Success) if(status != fr::Socket::Success)
bytes_read += read;
else
return status; return status;
bytes_remaining -= received;
bytes_read += received;
} }
return Socket::Status::Success; return Socket::Status::Success;
} }

View File

@ -2,6 +2,7 @@
// Created by fred on 20/12/16. // Created by fred on 20/12/16.
// //
#include <algorithm>
#include "frnetlib/SocketReactor.h" #include "frnetlib/SocketReactor.h"
namespace fr namespace fr
@ -10,27 +11,33 @@ namespace fr
void SocketReactor::add(const Socket &socket, std::function<void()> callback) void SocketReactor::add(const Socket &socket, std::function<void()> callback)
{ {
socket_selector.add(socket); socket_selector.add(socket);
callbacks.emplace_back(std::make_pair(&socket, callback));
} }
void SocketReactor::remove(const Socket &socket) void SocketReactor::remove(const Socket &socket)
{ {
socket_selector.remove(socket); socket_selector.remove(socket);
callbacks.erase(std::find_if(callbacks.begin(), callbacks.end(), [&](const std::pair<const fr::Socket*, std::function<void()>> &check) {
return check.first->get_socket_descriptor() == socket.get_socket_descriptor();
}));
} }
bool SocketReactor::wait(std::chrono::milliseconds timeout) bool SocketReactor::wait(std::chrono::milliseconds timeout)
{ {
bool found = false;
if(socket_selector.wait(timeout)) if(socket_selector.wait(timeout))
{ {
//Find which socket sent the activity //Find which socket sent the activity
for(auto &callback : callbacks) for(auto &callback : callbacks)
{ {
if(socket_selector.is_ready(callback.first)) if(socket_selector.is_ready(*callback.first))
{ {
//Call the socket's callback //Call the socket's callback
callback.second(); callback.second();
found = true;
} }
} }
} }
return false; return found;
} }
} }

View File

@ -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; received = 0;
if(unprocessed_buffer.size() < data_size) if(unprocessed_buffer.size() < buffer_size)
{ {
//Read RECV_CHUNK_SIZE bytes into the recv buffer //Read RECV_CHUNK_SIZE bytes into the recv buffer
ssize_t status = ::recv(socket_descriptor, recv_buffer.get(), RECV_CHUNK_SIZE, 0); ssize_t status = ::recv(socket_descriptor, recv_buffer.get(), RECV_CHUNK_SIZE, 0);
@ -80,12 +80,12 @@ namespace fr
return Socket::Status::Disconnected; return Socket::Status::Disconnected;
} }
if(received > data_size) if(received > buffer_size)
received = data_size; received = buffer_size;
} }
else else
{ {
received = data_size; received = buffer_size;
} }
//Copy data to where it needs to go //Copy data to where it needs to go