diff --git a/.gitignore b/.gitignore index f68392a..a478493 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ cmake-build-release CMakeCache\.txt pc/frnetlib.pc include/frnetlib/version.h +*.swp build diff --git a/README.md b/README.md index 71e9301..fc9a5ed 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Frnetlib is tested on both Linux and Windows and currently supports: # Connecting to a Socket: ```c++ -#include +#include fr::TcpSocket socket; if(socket.connect("127.0.0.1", "8081", std::chrono::seconds(10)) != fr::Socket::Status::Success) @@ -27,8 +27,8 @@ Here, we create a new fr::TcpSocket and connect it to an address. Simple. fr::Tc # Listening and accepting connections: ```c++ -#include -#include +#include +#include fr::TcpListener listener; @@ -51,14 +51,14 @@ Here we create a new fr::TcpListener, which is used to listen for incoming conne # Using SSL ```c++ -#include -#include -#include +#include +#include +#include -std::shared_ptr ssl_context(new fr::SSLContext("certs.crt")); //Creates a new 'SSL' context. This stores certificates and is shared between SSL enabled objects. +std::shared_ptr ssl_context(new fr::SSLContext()); //Creates a new 'SSL' context. This stores certificates and is shared between SSL enabled objects. ssl_conext->load_ca_certs_from_file(filepath); //This, or 'load_ca_certs_from_memory' should be called on the context, to load your SSL certificates. -fr::SSLListener listener(ssl_context, "crt_path", "pem_path", "private_key_path"); //This is the SSL equivilent to fr::TcpListener +fr::SSLListener listener(ssl_context, "pem_path", "private_key_path"); //This is the SSL equivilent to fr::TcpListener fr::SSLSocket socket(ssl_context); //This is the SSL equivilent to fr::TcpSocket @@ -71,7 +71,7 @@ SSLListener accepts a lot more arguments than its unencrypted counterpart, TcpLi # Sending packets: ```c++ -#include +#include fr::Packet packet; packet << "Hello there, I am" << (float)1.2 << "years old"; @@ -101,8 +101,8 @@ Effectively the reverse of sending packets. We call fr::TcpSocket::receive, pass # A simple HTTP server: ```c++ -#include -#include +#include +#include fr::TcpSocket client; //fr::TcpSocket for HTTP. fr::SSLSocket for HTTPS. fr::TcpListener listener; //Use an fr::SSLListener if HTTPS. @@ -149,8 +149,8 @@ fr::HttpRequest objects are used for dealing with data being sent *to* the serve # A simple HTTP client: ```c++ -#include -#include +#include +#include //Connect to the website example.com on port 80, with a 10 second connection timeout fr::TcpSocket socket; diff --git a/include/frnetlib/SSLListener.h b/include/frnetlib/SSLListener.h index 1a428b6..d5c41da 100644 --- a/include/frnetlib/SSLListener.h +++ b/include/frnetlib/SSLListener.h @@ -81,6 +81,20 @@ namespace fr */ int32_t get_socket_descriptor() const override; + /*! + * Gets the ssl context + * + * @return The SSLContext + */ + const std::shared_ptr &get_ssl_context()const; + + /*! + * Gets the ssl context + * + * @return The SSLContext + */ + std::shared_ptr &get_ssl_context(); + private: mbedtls_net_context listen_fd; mbedtls_ssl_config conf; diff --git a/include/frnetlib/SSLSocket.h b/include/frnetlib/SSLSocket.h index 322d205..3711538 100644 --- a/include/frnetlib/SSLSocket.h +++ b/include/frnetlib/SSLSocket.h @@ -21,9 +21,9 @@ namespace fr public: explicit SSLSocket(std::shared_ptr ssl_context) noexcept; ~SSLSocket() override; - SSLSocket(SSLSocket &&) = delete; + SSLSocket(SSLSocket &&); SSLSocket(const SSLSocket &) = delete; - void operator=(SSLSocket &&)=delete; + SSLSocket &operator=(SSLSocket &&); void operator=(const SSLSocket &)=delete; /*! @@ -126,6 +126,20 @@ namespace fr return is_blocking; } + /*! + * Gets the ssl context + * + * @return The SSLContext + */ + const std::shared_ptr &get_ssl_context()const; + + /*! + * Gets the ssl context + * + * @return The SSLContext + */ + std::shared_ptr &get_ssl_context(); + /*! * Checks to see if we're connected to a socket or not * @@ -151,4 +165,4 @@ namespace fr }; } -#endif //FRNETLIB_SSLSOCKET_H \ No newline at end of file +#endif //FRNETLIB_SSLSOCKET_H diff --git a/include/frnetlib/Socket.h b/include/frnetlib/Socket.h index 1660a36..fc20b2f 100644 --- a/include/frnetlib/Socket.h +++ b/include/frnetlib/Socket.h @@ -52,10 +52,10 @@ namespace fr }; Socket(); - Socket(Socket &&) =delete; + Socket(Socket &&); Socket(const Socket &) =delete; void operator=(const Socket &) =delete; - void operator=(Socket &&) =delete; + Socket &operator=(Socket &&); /*! * Converts an fr::Socket::Status value to a printable string @@ -314,4 +314,4 @@ namespace fr } -#endif //FRNETLIB_SOCKET_H \ No newline at end of file +#endif //FRNETLIB_SOCKET_H diff --git a/include/frnetlib/TcpSocket.h b/include/frnetlib/TcpSocket.h index 10d72ef..d79e562 100644 --- a/include/frnetlib/TcpSocket.h +++ b/include/frnetlib/TcpSocket.h @@ -16,9 +16,9 @@ namespace fr public: TcpSocket() noexcept; ~TcpSocket() override; - TcpSocket(TcpSocket &&) = delete; + TcpSocket(TcpSocket &&); TcpSocket(const TcpSocket &) = delete; - void operator=(TcpSocket &&)=delete; + TcpSocket &operator=(TcpSocket &&); void operator=(const TcpSocket &)=delete; /*! @@ -126,4 +126,4 @@ namespace fr } -#endif //FRNETLIB_TCPSOCKET_H \ No newline at end of file +#endif //FRNETLIB_TCPSOCKET_H diff --git a/include/frnetlib/Util.h b/include/frnetlib/Util.h new file mode 100644 index 0000000..54dae98 --- /dev/null +++ b/include/frnetlib/Util.h @@ -0,0 +1,40 @@ +// +// Created by rexy712 on 06/25/2021. +// + +#ifndef FRNETLIB_UTIL_H +#define FRNETLIB_UTIL_H + +#include +#include //size_t +#include //memcpy, memset + +namespace fr +{ + template + constexpr void swap(T& a, T& b) + { + T tmp = std::move(a); + a = std::move(b); + b = std::move(tmp); + } + + template + constexpr void swap(T (&a)[N], T (&b)[N]) + { + for(size_t i = 0;i < N;++i) + { + swap(a[i], b[i]); + } + } + + static inline mbedtls_ssl_config move_mbedtls_ssl_config(mbedtls_ssl_config &&src) + { + mbedtls_ssl_config retval = {}; + memcpy(&retval, &src, sizeof(src)); + memset(&src, 0, sizeof(src)); + return retval; + } +} + +#endif diff --git a/src/SSLListener.cpp b/src/SSLListener.cpp index 51796b0..f88d8e8 100644 --- a/src/SSLListener.cpp +++ b/src/SSLListener.cpp @@ -171,9 +171,19 @@ namespace fr } } + const std::shared_ptr &SSLListener::get_ssl_context()const + { + return ssl_context; + } + + std::shared_ptr &SSLListener::get_ssl_context() + { + return ssl_context; + } + bool SSLListener::connected() const { return listen_fd.fd > -1; } -} \ No newline at end of file +} diff --git a/src/SSLSocket.cpp b/src/SSLSocket.cpp index faf3890..84d4860 100644 --- a/src/SSLSocket.cpp +++ b/src/SSLSocket.cpp @@ -3,6 +3,7 @@ // #include "frnetlib/SSLSocket.h" +#include "frnetlib/Util.h" #include #include @@ -58,6 +59,29 @@ namespace fr mbedtls_ssl_config_free(&conf); } + SSLSocket::SSLSocket(SSLSocket &&s) + : Socket(std::move(s)), + ssl_context(std::move(s.ssl_context)), + ssl_socket_descriptor(std::move(s.ssl_socket_descriptor)), + ssl(std::move(s.ssl)), + conf(move_mbedtls_ssl_config(std::move(s.conf))), + should_verify(s.should_verify), + receive_timeout(s.receive_timeout), + is_blocking(s.is_blocking){} + + SSLSocket &SSLSocket::operator=(SSLSocket &&s) + { + Socket::operator=(std::move(s)); + ssl_context = std::move(s.ssl_context); + ssl_socket_descriptor = std::move(s.ssl_socket_descriptor); + ssl = std::move(s.ssl); + conf = move_mbedtls_ssl_config(std::move(s.conf)); + should_verify = s.should_verify; + receive_timeout = s.receive_timeout; + is_blocking = s.is_blocking; + return *this; + } + void SSLSocket::close_socket() { ssl = nullptr; @@ -284,9 +308,17 @@ namespace fr return -1; return ssl_socket_descriptor->fd; } + const std::shared_ptr &SSLSocket::get_ssl_context()const + { + return ssl_context; + } + std::shared_ptr &SSLSocket::get_ssl_context() + { + return ssl_context; + } bool SSLSocket::connected() const { return ssl_socket_descriptor && ssl_socket_descriptor->fd > -1; } -} \ No newline at end of file +} diff --git a/src/Socket.cpp b/src/Socket.cpp index 7fc3e1d..a274787 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -24,6 +24,23 @@ namespace fr init_wsa(); } + Socket::Socket(Socket &&s) + : fr_socket_remote_address(std::move(s.fr_socket_remote_address)), + ai_family(s.ai_family), + max_receive_size(s.max_receive_size), + socket_read_timeout(s.socket_read_timeout), + socket_write_timeout(s.socket_write_timeout){} + + Socket &Socket::operator=(Socket &&s) + { + fr_socket_remote_address = std::move(s.fr_socket_remote_address); + ai_family = s.ai_family; + max_receive_size = s.max_receive_size; + socket_read_timeout = s.socket_read_timeout; + socket_write_timeout = s.socket_write_timeout; + return *this; + } + Socket::Status Socket::send(const Sendable &obj) { if(!connected()) @@ -166,4 +183,4 @@ namespace fr { close_socket(); } -} \ No newline at end of file +} diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp index f37abda..26ff5e5 100644 --- a/src/TcpSocket.cpp +++ b/src/TcpSocket.cpp @@ -17,11 +17,24 @@ namespace fr } + TcpSocket::TcpSocket(TcpSocket &&t) + : Socket(std::move(t)), + socket_descriptor(std::exchange(t.socket_descriptor, -1)), + is_blocking(t.is_blocking){} + TcpSocket::~TcpSocket() { TcpSocket::close_socket(); } + TcpSocket &TcpSocket::operator=(TcpSocket &&t) + { + Socket::operator=(std::move(t)); + std::swap(socket_descriptor, t.socket_descriptor); + is_blocking = t.is_blocking; + return *this; + } + Socket::Status TcpSocket::send_raw(const char *data, size_t size, size_t &sent) { while(sent < size) @@ -257,4 +270,4 @@ namespace fr } -} \ No newline at end of file +}