From 49b25713361d4465b7ca90b7acb9b04182b3078b Mon Sep 17 00:00:00 2001 From: Michael Theall Date: Wed, 8 Apr 2020 16:53:47 -0500 Subject: [PATCH] Auto start/stop More fine-grained locking --- include/ftpServer.h | 8 +-- include/platform.h | 3 + source/3ds/platform.cpp | 36 ++++++++++-- source/ftpServer.cpp | 112 ++++++++++++++++++++++--------------- source/linux/platform.cpp | 5 ++ source/switch/platform.cpp | 11 ++++ 6 files changed, 121 insertions(+), 54 deletions(-) diff --git a/include/ftpServer.h b/include/ftpServer.h index 2174006..ff85a5c 100644 --- a/include/ftpServer.h +++ b/include/ftpServer.h @@ -58,11 +58,11 @@ private: /// \param port_ Port to listen on FtpServer (std::uint16_t port_); - /// \brief Handle when start button is pressed - void handleStartButton (); + /// \brief Handle when network is found + void handleNetworkFound (); - /// \brief Handle when stop button is pressed - void handleStopButton (); + /// \brief Handle when network is lost + void handleNetworkLost (); /// \brief Server loop void loop (); diff --git a/include/platform.h b/include/platform.h index 514966a..fd8c7d3 100644 --- a/include/platform.h +++ b/include/platform.h @@ -34,6 +34,9 @@ namespace platform /// \brief Initialize platform bool init (); +/// \brief Whether network is visible +bool networkVisible (); + /// \brief Platform loop bool loop (); diff --git a/source/3ds/platform.cpp b/source/3ds/platform.cpp index ec39990..4043ab6 100644 --- a/source/3ds/platform.cpp +++ b/source/3ds/platform.cpp @@ -34,10 +34,13 @@ #include "gfx.h" +#include + +#include #include #include #include -#include +#include namespace { @@ -51,9 +54,11 @@ constexpr auto SOCU_BUFFERSIZE = 0x100000; static_assert (SOCU_BUFFERSIZE % SOCU_ALIGN == 0); /// \brief Whether soc:u is active -bool s_socuActive = false; +std::atomic s_socuActive = false; /// \brief soc:u buffer u32 *s_socuBuffer = nullptr; +/// \brief ac:u fence +platform::Mutex s_acuFence; /// \brief Clear color constexpr auto CLEAR_COLOR = 0x204B7AFF; @@ -99,6 +104,20 @@ C3D_Tex s_gfxTexture; /// \brief Texture atlas metadata Tex3DS_Texture s_gfxT3x; +/// \brief Get network visibility +bool getNetworkVisibility () +{ + // serialize ac:u access from multiple threads + auto lock = std::scoped_lock (s_acuFence); + + // get wifi status + std::uint32_t wifi = 0; + if (R_FAILED (ACU_GetWifiStatus (&wifi)) || !wifi) + return false; + + return true; +} + /// \brief Start network void startNetwork () { @@ -106,9 +125,7 @@ void startNetwork () if (s_socuActive) return; - // get wifi status - std::uint32_t wifi = 0; - if (R_FAILED (ACU_GetWifiStatus (&wifi)) || !wifi) + if (!getNetworkVisibility ()) return; // allocate soc:u buffer @@ -302,6 +319,15 @@ bool platform::init () return true; } +bool platform::networkVisible () +{ + // check if soc:u is active + if (!s_socuActive) + return false; + + return getNetworkVisibility (); +} + bool platform::loop () { if (!aptMainLoop ()) diff --git a/source/ftpServer.cpp b/source/ftpServer.cpp index f391219..601f3e4 100644 --- a/source/ftpServer.cpp +++ b/source/ftpServer.cpp @@ -21,6 +21,7 @@ #include "ftpServer.h" #include "fs.h" +#include "platform.h" #include "imgui.h" @@ -35,6 +36,13 @@ #include using namespace std::chrono_literals; +#define LOCKED(x) \ + do \ + { \ + auto const lock = std::scoped_lock (m_lock); \ + x; \ + } while (0) + namespace { /// \brief Application start time @@ -60,8 +68,6 @@ FtpServer::FtpServer (std::uint16_t const port_) { Log::bind (m_log); - handleStartButton (); - m_thread = platform::Thread (std::bind (&FtpServer::threadFunc, this)); } @@ -78,27 +84,11 @@ void FtpServer::draw () #else ImGui::SetNextWindowSize (ImVec2 (width, height)); #endif + ImGui::SetNextWindowFocus (); ImGui::Begin (STATUS_STRING, nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); - { - auto const lock = std::scoped_lock (m_lock); - if (!m_socket) - { - if (ImGui::Button ("Start")) - handleStartButton (); - } - else if (ImGui::Button ("Stop")) - handleStopButton (); - - if (m_socket) - { - ImGui::SameLine (); - ImGui::TextUnformatted (m_name.c_str ()); - } - } - { auto const lock = std::scoped_lock (s_lock); if (!s_freeSpace.empty ()) @@ -108,6 +98,15 @@ void FtpServer::draw () } } + { + ImGui::SameLine (); + auto const lock = std::scoped_lock (m_lock); + if (m_socket) + ImGui::TextUnformatted (m_name.c_str ()); + else + ImGui::TextUnformatted ("Waiting for network..."); + } + ImGui::Separator (); #ifdef _3DS @@ -132,8 +131,11 @@ void FtpServer::draw () ImGui::Separator (); #endif - for (auto &session : m_sessions) - session->draw (); + { + auto lock = std::scoped_lock (m_lock); + for (auto &session : m_sessions) + session->draw (); + } ImGui::End (); } @@ -161,10 +163,13 @@ std::time_t FtpServer::startTime () return s_startTime; } -void FtpServer::handleStartButton () +void FtpServer::handleNetworkFound () { - if (m_socket) - return; + { + auto lock = std::scoped_lock (m_lock); + if (m_socket) + return; + } struct sockaddr_in addr; addr.sin_family = AF_INET; @@ -196,49 +201,66 @@ void FtpServer::handleStartButton () Log::info ("Started server at %s\n", m_name.c_str ()); - m_socket = std::move (socket); + LOCKED (m_socket = std::move (socket)); } -void FtpServer::handleStopButton () +void FtpServer::handleNetworkLost () { - m_socket.reset (); + { + UniqueSocket sock; + LOCKED (sock = std::move (m_socket)); + } + Log::info ("Stopped server at %s\n", m_name.c_str ()); } void FtpServer::loop () { + if (platform::networkVisible ()) + handleNetworkFound (); + + // poll listen socket + if (m_socket) { - // poll listen socket - auto const lock = std::scoped_lock (m_lock); - if (m_socket) + Socket::PollInfo info{*m_socket, POLLIN, 0}; + if (Socket::poll (&info, 1, 0ms) > 0) { - Socket::PollInfo info{*m_socket, POLLIN, 0}; - if (Socket::poll (&info, 1, 0ms) > 0) + auto socket = m_socket->accept (); + if (socket) { - auto socket = m_socket->accept (); - if (socket) - m_sessions.emplace_back (FtpSession::create (std::move (socket))); - else - handleStopButton (); + auto session = FtpSession::create (std::move (socket)); + LOCKED (m_sessions.emplace_back (std::move (session))); } + else + handleNetworkLost (); } } - // remove dead sessions - for (auto it = std::begin (m_sessions); it != std::end (m_sessions);) { - auto const &session = *it; - if (session->dead ()) - it = m_sessions.erase (it); - else - ++it; + std::vector deadSessions; + { + // remove dead sessions + auto lock = std::scoped_lock (m_lock); + auto it = std::begin (m_sessions); + while (it != std::end (m_sessions)) + { + auto &session = *it; + if (session->dead ()) + { + deadSessions.emplace_back (std::move (session)); + it = m_sessions.erase (it); + } + else + ++it; + } + } } // poll sessions if (!m_sessions.empty ()) { if (!FtpSession::poll (m_sessions)) - handleStopButton (); + handleNetworkLost (); } // avoid busy polling in background thread else diff --git a/source/linux/platform.cpp b/source/linux/platform.cpp index 20c9637..7d5e314 100644 --- a/source/linux/platform.cpp +++ b/source/linux/platform.cpp @@ -162,6 +162,11 @@ bool platform::init () return true; } +bool platform::networkVisible () +{ + return true; +} + bool platform::loop () { bool inactive; diff --git a/source/switch/platform.cpp b/source/switch/platform.cpp index 436aed5..a54ca45 100644 --- a/source/switch/platform.cpp +++ b/source/switch/platform.cpp @@ -40,6 +40,17 @@ bool platform::init () return true; } +bool platform::networkVisible () +{ + NifmInternetConnectionType type; + std::uint32_t wifi; + NifmInternetConnectionStatus status; + if (R_FAILED (nifmGetInternetConnectionStatus (&type, &wifi, &status))) + return false; + + return status == NifmInternetConnectionStatus_Connected; +} + bool platform::loop () { if (!appletMainLoop ())