From 70779fbe9c10733c34cd6db41e236af8fa2e3d9e Mon Sep 17 00:00:00 2001 From: Cloaked9000 Date: Tue, 20 Dec 2016 11:33:31 +0000 Subject: [PATCH] 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. --- CMakeLists.txt | 2 +- include/frnetlib/SocketReactor.h | 55 ++++++++++++++++++++++++++++++++ src/SSLSocket.cpp | 1 + src/Socket.cpp | 9 ++++++ src/SocketReactor.cpp | 36 +++++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 include/frnetlib/SocketReactor.h create mode 100644 src/SocketReactor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2de1d59..9771edf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/include/frnetlib/SocketReactor.h b/include/frnetlib/SocketReactor.h new file mode 100644 index 0000000..0419a36 --- /dev/null +++ b/include/frnetlib/SocketReactor.h @@ -0,0 +1,55 @@ +// +// Created by fred on 20/12/16. +// + +#ifndef FRNETLIB_SOCKETREACTOR_H +#define FRNETLIB_SOCKETREACTOR_H + +#include +#include +#include +#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 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>> callbacks; + fr::SocketSelector socket_selector; + + }; +} + + +#endif //FRNETLIB_SOCKETREACTOR_H diff --git a/src/SSLSocket.cpp b/src/SSLSocket.cpp index 28980bf..375a02e 100644 --- a/src/SSLSocket.cpp +++ b/src/SSLSocket.cpp @@ -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) diff --git a/src/Socket.cpp b/src/Socket.cpp index a913422..59e2986 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -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) { diff --git a/src/SocketReactor.cpp b/src/SocketReactor.cpp new file mode 100644 index 0000000..0b44553 --- /dev/null +++ b/src/SocketReactor.cpp @@ -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 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; + } +} \ No newline at end of file