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
{
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
*
@ -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
*/

View File

@ -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

View File

@ -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<std::pair<fr::Socket&, std::function<void()>>> callbacks;
std::vector<std::pair<const fr::Socket*, std::function<void()>>> callbacks;
fr::SocketSelector socket_selector;
};

View File

@ -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.

View File

@ -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;
}

View File

@ -2,6 +2,7 @@
// Created by fred on 20/12/16.
//
#include <algorithm>
#include "frnetlib/SocketReactor.h"
namespace fr
@ -10,27 +11,33 @@ namespace fr
void SocketReactor::add(const Socket &socket, std::function<void()> 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<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 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;
}
}

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;
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