Added SocketReactor & fixes

Sockets will immediately return fr::Socket::Status::Disconnected if an attempt to send/receive data is made whilst the connection is closed.

Added SocketReactor, which is effectively a little wrapper around fr::SocketSelector, but can automatically call a callback for a socket when data is received on it.
This commit is contained in:
Cloaked9000 2016-12-20 11:33:31 +00:00
parent 7017b64a15
commit 70779fbe9c
5 changed files with 102 additions and 1 deletions

View File

@ -17,7 +17,7 @@ endif()
set( INCLUDE_PATH "${PROJECT_SOURCE_DIR}/include" )
set( SOURCE_PATH "${PROJECT_SOURCE_DIR}/src" )
set(SOURCE_FILES main.cpp src/TcpSocket.cpp include/frnetlib/TcpSocket.h src/TcpListener.cpp include/frnetlib/TcpListener.h src/Socket.cpp include/frnetlib/Socket.h src/Packet.cpp include/frnetlib/Packet.h include/frnetlib/NetworkEncoding.h src/SocketSelector.cpp include/frnetlib/SocketSelector.h src/HttpSocket.cpp include/frnetlib/HttpSocket.h src/HttpRequest.cpp include/frnetlib/HttpRequest.h src/HttpResponse.cpp include/frnetlib/HttpResponse.h src/Http.cpp include/frnetlib/Http.h src/SSLSocket.cpp include/frnetlib/SSLSocket.h src/SSLListener.cpp include/frnetlib/SSLListener.h include/frnetlib/SSLContext.h)
set(SOURCE_FILES main.cpp src/TcpSocket.cpp include/frnetlib/TcpSocket.h src/TcpListener.cpp include/frnetlib/TcpListener.h src/Socket.cpp include/frnetlib/Socket.h src/Packet.cpp include/frnetlib/Packet.h include/frnetlib/NetworkEncoding.h src/SocketSelector.cpp include/frnetlib/SocketSelector.h src/HttpSocket.cpp include/frnetlib/HttpSocket.h src/HttpRequest.cpp include/frnetlib/HttpRequest.h src/HttpResponse.cpp include/frnetlib/HttpResponse.h src/Http.cpp include/frnetlib/Http.h src/SSLSocket.cpp include/frnetlib/SSLSocket.h src/SSLListener.cpp include/frnetlib/SSLListener.h include/frnetlib/SSLContext.h src/SocketReactor.cpp include/frnetlib/SocketReactor.h)
include_directories(include)

View File

@ -0,0 +1,55 @@
//
// Created by fred on 20/12/16.
//
#ifndef FRNETLIB_SOCKETREACTOR_H
#define FRNETLIB_SOCKETREACTOR_H
#include <chrono>
#include <functional>
#include <vector>
#include "Socket.h"
#include "SocketSelector.h"
namespace fr
{
class SocketReactor
{
public:
SocketReactor(const SocketReactor&)=delete;
SocketReactor(SocketReactor&&) noexcept = default;
/*!
* Adds a socket to the selector. Note that SocketSelector
* does not keep a copy of the object, just a handle, it's
* up to you to store your fr::Sockets.
*
* @param socket The socket to add.
* @param callback A function to call when the socket shows activity. Remember to remove it from the reactor if the client has disconnected.
*/
void add(const Socket &socket, std::function<void()> callback);
/*!
* Removes a socket from the socket selector.
*
* @param socket The socket to remove.
*/
void remove(const Socket &socket);
/*!
* Waits for a socket to become ready.
*
* @param timeout The amount of time wait should block for before timing out.
* @return True if a socket is ready. False if it timed out.
*/
bool wait(std::chrono::milliseconds timeout = std::chrono::milliseconds(0));
private:
std::vector<std::pair<fr::Socket&, std::function<void()>>> callbacks;
fr::SocketSelector socket_selector;
};
}
#endif //FRNETLIB_SOCKETREACTOR_H

View File

@ -65,6 +65,7 @@ namespace fr
if(read == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
{
is_connected = false;
return Socket::Status::Disconnected;
}
else if(read <= 0)

View File

@ -31,6 +31,9 @@ namespace fr
Socket::Status Socket::send(const Packet &packet)
{
if(!is_connected)
return Socket::Disconnected;
//Get packet data
std::string data = packet.get_buffer();
@ -45,6 +48,9 @@ namespace fr
Socket::Status Socket::receive(Packet &packet)
{
if(!is_connected)
return Socket::Disconnected;
Socket::Status status;
//Try to read packet length
@ -68,6 +74,9 @@ namespace fr
Socket::Status Socket::receive_all(void *dest, size_t size)
{
if(!is_connected)
return Socket::Disconnected;
size_t bytes_read = 0;
while(bytes_read < size)
{

36
src/SocketReactor.cpp Normal file
View File

@ -0,0 +1,36 @@
//
// Created by fred on 20/12/16.
//
#include "frnetlib/SocketReactor.h"
namespace fr
{
void SocketReactor::add(const Socket &socket, std::function<void()> callback)
{
socket_selector.add(socket);
}
void SocketReactor::remove(const Socket &socket)
{
socket_selector.remove(socket);
}
bool SocketReactor::wait(std::chrono::milliseconds timeout)
{
if(socket_selector.wait(timeout))
{
//Find which socket sent the activity
for(auto &callback : callbacks)
{
if(socket_selector.is_ready(callback.first))
{
//Call the socket's callback
callback.second();
}
}
}
return false;
}
}