From aef2d050f57e37c39a55c15369eaa88ef7f3a1b1 Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 16 Aug 2025 09:13:07 -0400 Subject: [PATCH] Improve memory management --- sstp/main.cpp | 6 ++++-- sstp/socketconnectionreceiver.cpp | 25 +++++++++++++++++++--- sstp/socketconnectionreceiver.hpp | 17 +++++++++++++++ sstp/socketserver.cpp | 35 ++++++++++++++++++++++++++++--- sstp/socketserver.hpp | 7 +++++++ 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/sstp/main.cpp b/sstp/main.cpp index 4f577bb..0ae95dd 100644 --- a/sstp/main.cpp +++ b/sstp/main.cpp @@ -28,7 +28,7 @@ int main(int argc, char **argv) { int returnCode(0); Profiler profiler; - String version = "1.00"; + String version = "0.1.0.1"; // major version, minor version, patch, build std::cout << "sstp version " << version.str() << std::endl; try @@ -78,6 +78,8 @@ int main(int argc, char **argv) } /// @brief [0]=program [1]=SERVERMODE [2]={port} +/// @Note Currently this method will never return. The application is terminate with CTRL-C. Ideally, we would exit is some cleaner fashion +/// perhaps by implementing a CTRL-C hook and then destroying the SocketServer properly by calling it's destructor. See SocketServer::~SocketServer() /// @param commands void handleServer(Block &commands) { @@ -91,7 +93,7 @@ void handleServer(Block &commands) int port = commands[2].toInt(); std::cout << commands[1] << ":" << commands[2] << std::endl; SocketServer socketServer(commands[2].toInt()); - socketServer.listen(); + socketServer.listen(); std::cout << "Done, total took " << Utility::formatNumber(profiler.end()) << "(ms)" << std::endl; } diff --git a/sstp/socketconnectionreceiver.cpp b/sstp/socketconnectionreceiver.cpp index fb83155..0d395c8 100644 --- a/sstp/socketconnectionreceiver.cpp +++ b/sstp/socketconnectionreceiver.cpp @@ -2,17 +2,36 @@ #include #include + +SocketConnectionReceiver::SocketConnectionReceiver() +: mSocket(-1), mIsRunnable(true) +{ +} + + /// @brief After a connection has been accepted the SocketConnectionReceiver is initialized with the incoming socket /// @param socket /// @param internalSocketAddress SocketConnectionReceiver::SocketConnectionReceiver(int socket, sockaddr_in internalSocketAddress) -: mSocket(socket), mInternalSocketAddress(internalSocketAddress) +: mSocket(socket), mInternalSocketAddress(internalSocketAddress), mIsRunnable(true) { } +/// @brief Initialize a SocketConnectionReceiver. +/// @param socket +/// @param internalSocketAddress +void SocketConnectionReceiver::initialize(int socket, sockaddr_in internalSocketAddress) +{ + close(); + mSocket=socket; + mInternalSocketAddress = internalSocketAddress; +} + + /// @brief The destructor will close the socket SocketConnectionReceiver::~SocketConnectionReceiver() -{ +{ + isRunnable(false); close(); } @@ -31,7 +50,7 @@ void SocketConnectionReceiver::close(void) void SocketConnectionReceiver::threadFunction(int data) { String line; - while(true) + while(mIsRunnable) { readLine(line); if(0==line.length()) diff --git a/sstp/socketconnectionreceiver.hpp b/sstp/socketconnectionreceiver.hpp index 0a75b11..6ec3994 100644 --- a/sstp/socketconnectionreceiver.hpp +++ b/sstp/socketconnectionreceiver.hpp @@ -16,11 +16,15 @@ class SocketConnectionReceiver { public: + SocketConnectionReceiver(); SocketConnectionReceiver(int socket, sockaddr_in inernalSocketAddress); virtual ~SocketConnectionReceiver(); + void initialize(int socket, sockaddr_in inernalSocketAddress); void close(void); private: static constexpr size_t BUFFER_LENGTH=65536; // this is the buffer length for the socket + void isRunnable(bool isRunnable); + bool isRunnable(void); void threadFunction(int data); bool handlePut(Block &commands); void handleQuit(void); @@ -32,6 +36,19 @@ class SocketConnectionReceiver friend class SocketServer; char mBuffer[BUFFER_LENGTH] = {0}; int mSocket; + bool mIsRunnable; sockaddr_in mInternalSocketAddress; }; + +inline +void SocketConnectionReceiver::isRunnable(bool isRunnable) +{ + mIsRunnable=isRunnable; +} + +inline +bool SocketConnectionReceiver::isRunnable(void) +{ + return mIsRunnable; +} #endif \ No newline at end of file diff --git a/sstp/socketserver.cpp b/sstp/socketserver.cpp index fd8643b..bd764d4 100644 --- a/sstp/socketserver.cpp +++ b/sstp/socketserver.cpp @@ -40,9 +40,32 @@ SocketServer::SocketServer(int port) /// @brief Close down the listener SocketServer::~SocketServer() { - close(); + shutdownConnectionReceivers(); + join(); // Then join all socket threads + close(); // close the listener socket + } +/// @brief Join all threads +/// @param +void SocketServer::join(void) +{ + for (std::thread& executionThread : mExecutionThreads) + { + if (executionThread.joinable()) + { + executionThread.join(); + } + } +} + +/// @brief Remove object references to the connection receivers. This will force socket threads to exit and close connections +void SocketServer::shutdownConnectionReceivers() +{ + mSocketConnectionReceivers.remove(); +} + + /// @brief returns true if we have a valid socket connection otherwise false /// @return bool SocketServer::isOkay(void) @@ -75,8 +98,14 @@ void SocketServer::listen(void) close(); return; } - SocketConnectionReceiver socketConnectionReceiver(socket, internalSocketAddress); - mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, &socketConnectionReceiver, 0)); + mSocketConnectionReceivers.insert(SmartPointer()); + SmartPointer &pSocketConnectionReceiver = mSocketConnectionReceivers[mSocketConnectionReceivers.size()-1]; + pSocketConnectionReceiver = ::new SocketConnectionReceiver(socket, internalSocketAddress); + pSocketConnectionReceiver.disposition(PointerDisposition::Delete); + mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, *pSocketConnectionReceiver, 0)); + +// SocketConnectionReceiver socketConnectionReceiver(socket, internalSocketAddress); +// mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, &socketConnectionReceiver, 0)); } } diff --git a/sstp/socketserver.hpp b/sstp/socketserver.hpp index bcfe24b..6a55e5c 100644 --- a/sstp/socketserver.hpp +++ b/sstp/socketserver.hpp @@ -13,6 +13,9 @@ #include #include #include +#include + +class SocketConnectionReceiver; class SocketServer { @@ -24,11 +27,15 @@ class SocketServer bool isOkay(void); private: static constexpr int MAX_CONNECTIONS=10; // The maximum connections to be queued at a time + void shutdownConnectionReceivers(); + void join(void); + bool mIsOkay; int mListenPort; int mSocketFileDescriptor; struct sockaddr_in mInternalSocketAddress; socklen_t mAddressLength = sizeof(mInternalSocketAddress); std::vector mExecutionThreads; + Block> mSocketConnectionReceivers; }; #endif \ No newline at end of file