Add access point for Switch

This commit is contained in:
Michael Theall 2020-12-11 19:15:33 -06:00
parent 852669818d
commit 709e24d458
15 changed files with 600 additions and 87 deletions

View File

@ -86,7 +86,7 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) \
CC := `which ccache 2>/dev/null` $(CC)
CXX := `which ccache 2>/dev/null` $(CXX)
LIBS := `$(PREFIX)pkg-config --libs libzstd` -ldeko3dd -lnx
LIBS := `$(PREFIX)pkg-config --libs libzstd` -ldeko3d -lnx
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@ -20,8 +20,11 @@
#pragma once
#include "platform.h"
#include <cstdint>
#include <memory>
#include <mutex>
#include <string>
class FtpConfig;
@ -40,6 +43,10 @@ public:
/// \param path_ Path to config file
static UniqueFtpConfig load (char const *path_);
#ifndef NDS
std::lock_guard<platform::Mutex> lockGuard ();
#endif
/// \brief Save config
/// \param path_ Path to config file
bool save (char const *path_);
@ -59,6 +66,17 @@ public:
bool getMTime () const;
#endif
#ifdef __SWITCH__
/// \brief Whether to enable access point
bool enableAP () const;
/// \brief Access point SSID
std::string const &ssid () const;
/// \brief Access point passphrase
std::string const &passphrase () const;
#endif
/// \brief Set user
/// \param user_ User
void setUser (std::string const &user_);
@ -81,9 +99,28 @@ public:
void setGetMTime (bool getMTime_);
#endif
#ifdef __SWITCH__
/// \brief Set whether to enable access point
/// \param enable_ Whether to enable access point
void setEnableAP (bool enable_);
/// \brief Set access point SSID
/// \param ssid_ SSID
void setSSID (std::string const &ssid_);
/// \brief Set access point passphrase
/// \param passphrase_ Passphrase
void setPassphrase (std::string const &passphrase_);
#endif
private:
FtpConfig ();
#ifndef NDS
/// \brief Mutex
mutable platform::Mutex m_lock;
#endif
/// \brief Username
std::string m_user;
@ -97,4 +134,15 @@ private:
/// \brief Whether to get mtime
bool m_getMTime = true;
#endif
#ifdef __SWITCH__
/// \brief Whether to enable access point
bool m_enableAP = false;
/// \brief Access point SSID
std::string m_ssid = "ftpd";
/// \brief Access point passphrase
std::string m_passphrase;
#endif
};

View File

@ -67,6 +67,7 @@ private:
/// \brief Handle when network is lost
void handleNetworkLost ();
#ifndef CLASSIC
/// \brief Show menu in the current window
void showMenu ();
@ -75,6 +76,7 @@ private:
/// \brief Show about window
void showAbout ();
#endif
/// \brief Server loop
void loop ();
@ -108,6 +110,12 @@ private:
#ifndef CLASSIC
/// \brief Whether to show settings menu
bool m_showSettings = false;
#ifdef __SWITCH__
/// \brief Whether to show access point menu
bool m_showAP = false;
#endif
/// \brief Whether to show about window
bool m_showAbout = false;
@ -124,5 +132,19 @@ private:
/// \brief getMTime setting
bool m_getMTimeSetting;
#endif
#ifdef __SWITCH__
/// \brief Whether an error occurred enabling access point
std::atomic<bool> m_apError = false;
/// \brief Enable access point setting
bool m_enableAPSetting;
/// \brief Access point SSID setting
std::string m_ssidSetting;
/// \brief Access point passphrase setting
std::string m_passphraseSetting;
#endif
#endif
};

View File

@ -20,6 +20,8 @@
#pragma once
#include "sockAddr.h"
#if defined(NDS)
#include <nds.h>
#elif defined(_3DS)
@ -44,9 +46,31 @@ namespace platform
/// \brief Initialize platform
bool init ();
#ifdef __SWITCH__
/// \brief Enable access point
/// \param enable_ Whether to enable access point
/// \param ssid_ SSID
/// \param passphrase_ Passphrase
bool enableAP (bool enable_, std::string const &ssid_, std::string const &passphrase_);
/// \brief Check if SSID is valid
/// \param ssid_ SSID to check
/// \returns empty string on success, error message on failure
char const *validateSSID (std::string const &ssid_);
/// \brief Check if passphrase is valid
/// \param passphrase_ Passphrase to check
/// \returns empty string on success, error message on failure
char const *validatePassphrase (std::string const &passphrase_);
#endif
/// \brief Whether network is visible
bool networkVisible ();
/// \brief Get network address
/// \param[out] addr_ Network address
bool networkAddress (SockAddr &addr_);
/// \brief Platform loop
bool loop ();

View File

@ -94,8 +94,12 @@ public:
/// \brief Address port
std::uint16_t port () const;
/// \brief Set address port
/// \param port_ Port to set
bool setPort (std::uint16_t port_);
/// \brief Address name
/// \param buffer_
/// \param buffer_ Buffer to hold name
/// \param size_ Size of buffer_
/// \retval buffer_ success
/// \retval nullptr failure

View File

@ -165,7 +165,7 @@ void handleAPTHook (APT_HookType const type_, void *const param_)
bool getNetworkVisibility ()
{
// serialize ac:u access from multiple threads
auto lock = std::scoped_lock (s_acuFence);
auto lock = std::lock_guard (s_acuFence);
// get wifi status
std::uint32_t wifi = 0;
@ -428,6 +428,16 @@ bool platform::networkVisible ()
return getNetworkVisibility ();
}
bool platform::networkAddress (SockAddr &addr_)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = gethostid ();
addr_ = addr;
return true;
}
bool platform::loop ()
{
if (!aptMainLoop ())

View File

@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <limits>
#include <mutex>
namespace
{
@ -162,6 +163,21 @@ UniqueFtpConfig FtpConfig::load (char const *const path_)
else
error ("Invalid value for mtime: %s\n", val.c_str ());
}
#endif
#ifdef __SWITCH__
else if (key == "ap")
{
if (val == "0")
config->m_enableAP = false;
else if (val == "1")
config->m_enableAP = true;
else
error ("Invalid value for ap: %s\n", val.c_str ());
}
else if (key == "ssid")
config->m_ssid = val;
else if (key == "passphrase")
config->m_passphrase = val;
#endif
}
@ -170,6 +186,13 @@ UniqueFtpConfig FtpConfig::load (char const *const path_)
return config;
}
#ifndef NDS
std::lock_guard<platform::Mutex> FtpConfig::lockGuard ()
{
return std::lock_guard<platform::Mutex> (m_lock);
}
#endif
bool FtpConfig::save (char const *const path_)
{
if (!mkdirParent (path_))
@ -189,6 +212,14 @@ bool FtpConfig::save (char const *const path_)
std::fprintf (fp, "mtime=%u\n", m_getMTime);
#endif
#ifdef __SWITCH__
std::fprintf (fp, "ap=%u\n", m_enableAP);
if (!m_ssid.empty ())
std::fprintf (fp, "ssid=%s\n", m_ssid.c_str ());
if (!m_passphrase.empty ())
std::fprintf (fp, "passphrase=%s\n", m_passphrase.c_str ());
#endif
return true;
}
@ -214,6 +245,23 @@ bool FtpConfig::getMTime () const
}
#endif
#ifdef __SWITCH__
bool FtpConfig::enableAP () const
{
return m_enableAP;
}
std::string const &FtpConfig::ssid () const
{
return m_ssid;
}
std::string const &FtpConfig::passphrase () const
{
return m_passphrase;
}
#endif
void FtpConfig::setUser (std::string const &user_)
{
m_user = user_.substr (0, user_.find_first_of ('\0'));
@ -255,3 +303,20 @@ void FtpConfig::setGetMTime (bool const getMTime_)
m_getMTime = getMTime_;
}
#endif
#ifdef __SWITCH__
void FtpConfig::setEnableAP (bool const enable_)
{
m_enableAP = enable_;
}
void FtpConfig::setSSID (std::string const &ssid_)
{
m_ssid = ssid_.substr (0, ssid_.find_first_of ('\0'));
}
void FtpConfig::setPassphrase (std::string const &passphrase_)
{
m_passphrase = passphrase_.substr (0, passphrase_.find_first_of ('\0'));
}
#endif

View File

@ -36,10 +36,12 @@
#include <sys/statvfs.h>
#include <unistd.h>
#include <cctype>
#include <chrono>
#include <cstdio>
#include <cstring>
#include <mutex>
#include <string_view>
#include <thread>
using namespace std::chrono_literals;
@ -49,7 +51,7 @@ using namespace std::chrono_literals;
#define LOCKED(x) \
do \
{ \
auto const lock = std::scoped_lock (m_lock); \
auto const lock = std::lock_guard (m_lock); \
x; \
} while (0)
#endif
@ -95,7 +97,7 @@ void FtpServer::draw ()
{
char port[7];
#ifndef NDS
auto lock = std::scoped_lock (m_lock);
auto const lock = std::lock_guard (m_lock);
#endif
if (m_socket)
std::sprintf (port, ":%u", m_socket->sockName ().port ());
@ -120,7 +122,7 @@ void FtpServer::draw ()
{
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
auto const lock = std::lock_guard (s_lock);
#endif
if (!s_freeSpace.empty ())
{
@ -134,7 +136,7 @@ void FtpServer::draw ()
{
#ifndef NDS
auto lock = std::scoped_lock (m_lock);
auto const lock = std::lock_guard (m_lock);
#endif
consoleSelect (&g_sessionConsole);
std::fputs ("\x1b[2J", stdout);
@ -164,7 +166,7 @@ void FtpServer::draw ()
char title[64];
{
auto const serverLock = std::scoped_lock (m_lock);
auto const serverLock = std::lock_guard (m_lock);
std::snprintf (title,
sizeof (title),
STATUS_STRING " %s###ftpd",
@ -210,7 +212,7 @@ void FtpServer::draw ()
#endif
{
auto lock = std::scoped_lock (m_lock);
auto const lock = std::lock_guard (m_lock);
for (auto &session : m_sessions)
session->draw ();
}
@ -231,7 +233,7 @@ UniqueFtpServer FtpServer::create ()
std::string FtpServer::getFreeSpace ()
{
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
auto const lock = std::lock_guard (s_lock);
#endif
return s_freeSpace;
}
@ -249,7 +251,7 @@ void FtpServer::updateFreeSpace ()
auto freeSpace = fs::printSize (static_cast<std::uint64_t> (st.f_bsize) * st.f_bfree);
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
auto const lock = std::lock_guard (s_lock);
#endif
if (freeSpace != s_freeSpace)
s_freeSpace = std::move (freeSpace);
@ -262,22 +264,26 @@ std::time_t FtpServer::startTime ()
void FtpServer::handleNetworkFound ()
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
#if defined(NDS)
addr.sin_addr = Wifi_GetIPInfo (nullptr, nullptr, nullptr, nullptr);
#elif defined(_3DS) || defined(__SWITCH__)
addr.sin_addr.s_addr = gethostid ();
#else
addr.sin_addr.s_addr = INADDR_ANY;
SockAddr addr;
if (!platform::networkAddress (addr))
return;
std::uint16_t port;
{
#ifndef NDS
auto const lock = m_config->lockGuard ();
#endif
addr.sin_port = htons (m_config->port ());
port = m_config->port ();
}
addr.setPort (port);
auto socket = Socket::create ();
if (!socket)
return;
if (m_config->port () != 0 && !socket->setReuseAddress (true))
if (port != 0 && !socket->setReuseAddress (true))
return;
if (!socket->bind (addr))
@ -290,7 +296,7 @@ void FtpServer::handleNetworkFound ()
auto const name = sockName.name ();
m_name.resize (std::strlen (name) + 3 + 5);
m_name.resize (std::sprintf (&m_name[0], "[%s]:%u", name, sockName.port ()));
m_name.resize (std::sprintf (m_name.data (), "[%s]:%u", name, sockName.port ()));
info ("Started server at %s\n", m_name.c_str ());
@ -314,9 +320,9 @@ void FtpServer::handleNetworkLost ()
info ("Stopped server at %s\n", m_name.c_str ());
}
#ifndef CLASSIC
void FtpServer::showMenu ()
{
#ifndef CLASSIC
auto const prevShowSettings = m_showSettings;
auto const prevShowAbout = m_showAbout;
@ -343,6 +349,10 @@ void FtpServer::showMenu ()
{
if (!prevShowSettings)
{
#ifndef NDS
auto const lock = m_config->lockGuard ();
#endif
m_userSetting = m_config->user ();
m_userSetting.resize (32);
@ -355,7 +365,16 @@ void FtpServer::showMenu ()
m_getMTimeSetting = m_config->getMTime ();
#endif
info ("Open \"Settings\" popup\n");
#ifdef __SWITCH__
m_enableAPSetting = m_config->enableAP ();
m_ssidSetting = m_config->ssid ();
m_ssidSetting.resize (19);
m_passphraseSetting = m_config->passphrase ();
m_passphraseSetting.resize (63);
#endif
ImGui::OpenPopup ("Settings");
}
@ -373,7 +392,6 @@ void FtpServer::showMenu ()
void FtpServer::showSettings ()
{
#ifndef CLASSIC
#ifdef _3DS
auto const &io = ImGui::GetIO ();
auto const width = io.DisplaySize.x;
@ -388,11 +406,13 @@ void FtpServer::showSettings ()
if (ImGui::BeginPopupModal ("Settings", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
#endif
{
ImGui::InputText (
"User", &m_userSetting[0], m_userSetting.size (), ImGuiInputTextFlags_AutoSelectAll);
ImGui::InputText ("User",
m_userSetting.data (),
m_userSetting.size (),
ImGuiInputTextFlags_AutoSelectAll);
ImGui::InputText ("Pass",
&m_passSetting[0],
m_passSetting.data (),
m_passSetting.size (),
ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_Password);
@ -408,6 +428,26 @@ void FtpServer::showSettings ()
ImGui::Checkbox ("Get mtime", &m_getMTimeSetting);
#endif
#ifdef __SWITCH__
ImGui::Checkbox ("Enable Access Point", &m_enableAPSetting);
ImGui::InputText ("SSID",
m_ssidSetting.data (),
m_ssidSetting.size (),
ImGuiInputTextFlags_AutoSelectAll);
auto const ssidError = platform::validateSSID (m_ssidSetting);
if (ssidError)
ImGui::TextColored (ImVec4 (1.0f, 0.4f, 0.4f, 1.0f), ssidError);
ImGui::InputText ("Passphrase",
m_passphraseSetting.data (),
m_passphraseSetting.size (),
ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_Password);
auto const passphraseError = platform::validatePassphrase (m_passphraseSetting);
if (passphraseError)
ImGui::TextColored (ImVec4 (1.0f, 0.4f, 0.4f, 1.0f), passphraseError);
#endif
auto const apply = ImGui::Button ("Apply", ImVec2 (100, 0));
ImGui::SameLine ();
auto const save = ImGui::Button ("Save", ImVec2 (100, 0));
@ -419,6 +459,10 @@ void FtpServer::showSettings ()
m_showSettings = false;
ImGui::CloseCurrentPopup ();
#ifndef NDS
auto const lock = m_config->lockGuard ();
#endif
m_config->setUser (m_userSetting);
m_config->setPass (m_passSetting);
m_config->setPort (m_portSetting);
@ -427,12 +471,24 @@ void FtpServer::showSettings ()
m_config->setGetMTime (m_getMTimeSetting);
#endif
#ifdef __SWITCH__
m_config->setEnableAP (m_enableAPSetting);
m_config->setSSID (m_ssidSetting);
m_config->setPassphrase (m_passphraseSetting);
m_apError = false;
#endif
UniqueSocket socket;
LOCKED (socket = std::move (m_socket));
}
if (save && !m_config->save (FTPDCONFIG))
error ("Failed to save config\n");
{
#ifndef NDS
auto const lock = m_config->lockGuard ();
#endif
if (save && !m_config->save (FTPDCONFIG))
error ("Failed to save config\n");
}
if (apply || save || cancel)
{
@ -442,13 +498,10 @@ void FtpServer::showSettings ()
ImGui::EndPopup ();
}
#endif
#endif
}
void FtpServer::showAbout ()
{
#ifndef CLASSIC
auto const &io = ImGui::GetIO ();
auto const width = io.DisplaySize.x;
auto const height = io.DisplaySize.y;
@ -539,13 +592,31 @@ void FtpServer::showAbout ()
ImGui::EndPopup ();
}
#endif
}
#endif
void FtpServer::loop ()
{
if (!m_socket)
{
#ifdef __SWITCH__
if (!m_apError)
{
bool enable;
std::string ssid;
std::string passphrase;
{
auto const lock = m_config->lockGuard ();
enable = m_config->enableAP ();
ssid = m_config->ssid ();
passphrase = m_config->passphrase ();
}
m_apError = !platform::enableAP (enable, ssid, passphrase);
}
#endif
if (platform::networkVisible ())
handleNetworkFound ();
}
@ -582,7 +653,7 @@ void FtpServer::loop ()
{
// remove dead sessions
#ifndef NDS
auto lock = std::scoped_lock (m_lock);
auto const lock = std::lock_guard (m_lock);
#endif
auto it = std::begin (m_sessions);
while (it != std::end (m_sessions))

View File

@ -50,7 +50,7 @@ using namespace std::chrono_literals;
#define LOCKED(x) \
do \
{ \
auto const lock = std::scoped_lock (m_lock); \
auto const lock = std::lock_guard (m_lock); \
x; \
} while (0)
#endif
@ -293,10 +293,15 @@ FtpSession::FtpSession (FtpConfig &config_, UniqueSocket commandSocket_)
m_mlstUnixMode (false),
m_devZero (false)
{
if (m_config.user ().empty ())
m_authorizedUser = true;
if (m_config.pass ().empty ())
m_authorizedPass = true;
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
if (m_config.user ().empty ())
m_authorizedUser = true;
if (m_config.pass ().empty ())
m_authorizedPass = true;
}
char buffer[32];
std::sprintf (buffer, "Session#%p", this);
@ -313,7 +318,7 @@ FtpSession::FtpSession (FtpConfig &config_, UniqueSocket commandSocket_)
bool FtpSession::dead ()
{
#ifndef NDS
auto const lock = std::scoped_lock (m_lock);
auto const lock = std::lock_guard (m_lock);
#endif
if (m_commandSocket || m_pasvSocket || m_dataSocket)
return false;
@ -324,7 +329,7 @@ bool FtpSession::dead ()
void FtpSession::draw ()
{
#ifndef NDS
auto const lock = std::scoped_lock (m_lock);
auto const lock = std::lock_guard (m_lock);
#endif
#ifdef CLASSIC
@ -610,7 +615,7 @@ void FtpSession::setState (State const state_, bool const closePasv_, bool const
{
{
#ifndef NDS
auto lock = std::scoped_lock (m_lock);
auto lock = std::lock_guard (m_lock);
#endif
m_restartPosition = 0;
@ -1673,7 +1678,13 @@ bool FtpSession::listTransfer ()
else if (m_xferDirMode == XferDirMode::NLST)
getmtime = false;
if (getmtime && m_config.getMTime ())
{
auto const lock = m_config.lockGuard ();
if (!m_config.getMTime ())
getmtime = false;
}
if (getmtime)
{
std::uint64_t mtime = 0;
auto const rc = archive_getmtime (fullPath.c_str (), &mtime);
@ -2159,13 +2170,24 @@ void FtpSession::PASS (char const *args_)
m_authorizedPass = false;
if (!m_config.user ().empty () && !m_authorizedUser)
std::string user;
std::string pass;
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
user = m_config.user ();
pass = m_config.pass ();
}
if (!user.empty () && !m_authorizedUser)
{
sendResponse ("430 User not authorized\r\n");
return;
}
if (m_config.pass ().empty () || m_config.pass () == args_)
if (pass.empty () || pass == args_)
{
m_authorizedPass = true;
sendResponse ("230 OK\r\n");
@ -2544,19 +2566,40 @@ void FtpSession::SITE (char const *args_)
if (::strcasecmp (command.c_str (), "USER") == 0)
{
m_config.setUser (arg);
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
m_config.setUser (arg);
}
sendResponse ("200 OK\r\n");
return;
}
else if (::strcasecmp (command.c_str (), "PASS") == 0)
{
m_config.setPass (arg);
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
m_config.setPass (arg);
}
sendResponse ("200 OK\r\n");
return;
}
else if (::strcasecmp (command.c_str (), "PORT") == 0)
{
if (!m_config.setPort (arg))
bool error = false;
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
error = !m_config.setPort (arg);
}
if (error)
{
sendResponse ("550 %s\r\n", std::strerror (errno));
return;
@ -2569,9 +2612,19 @@ void FtpSession::SITE (char const *args_)
else if (::strcasecmp (command.c_str (), "MTIME") == 0)
{
if (arg == "0")
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
m_config.setGetMTime (false);
}
else if (arg == "1")
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
m_config.setGetMTime (true);
}
else
{
sendResponse ("550 %s\r\n", std::strerror (EINVAL));
@ -2581,7 +2634,16 @@ void FtpSession::SITE (char const *args_)
#endif
else if (::strcasecmp (command.c_str (), "SAVE") == 0)
{
if (!m_config.save (FTPDCONFIG))
bool error;
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
error = !m_config.save (FTPDCONFIG);
}
if (error)
{
sendResponse ("550 %s\r\n", std::strerror (errno));
return;
@ -2730,10 +2792,21 @@ void FtpSession::USER (char const *args_)
m_authorizedUser = false;
if (m_config.user ().empty () || m_config.user () == args_)
std::string user;
std::string pass;
{
#ifndef NDS
auto const lock = m_config.lockGuard ();
#endif
user = m_config.user ();
pass = m_config.pass ();
}
if (user.empty () || user == args_)
{
m_authorizedUser = true;
if (m_config.pass ().empty ())
if (pass.empty ())
{
sendResponse ("230 OK\r\n");
return;

View File

@ -169,6 +169,16 @@ bool platform::networkVisible ()
return true;
}
bool platform::networkAddress (SockAddr &addr_)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr_ = addr;
return true;
}
bool platform::loop ()
{
bool inactive;

View File

@ -79,7 +79,7 @@ platform::Mutex s_lock;
void drawLog ()
{
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
auto const lock = std::lock_guard (s_lock);
#endif
#ifdef CLASSIC
@ -211,7 +211,7 @@ void addLog (LogLevel const level_, char const *const fmt_, va_list ap_)
std::vsnprintf (buffer, sizeof (buffer), fmt_, ap_);
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
auto const lock = std::lock_guard (s_lock);
#endif
#ifndef NDEBUG
// std::fprintf (stderr, "%s", s_prefix[level_]);
@ -239,7 +239,7 @@ void addLog (LogLevel const level_, std::string_view const message_)
}
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
auto const lock = std::lock_guard (s_lock);
#endif
#ifndef NDEBUG
// std::fprintf (stderr, "%s", s_prefix[level_]);

View File

@ -73,6 +73,16 @@ bool platform::networkVisible ()
return false;
}
bool platform::networkAddress (SockAddr &addr_)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr = Wifi_GetIPInfo (nullptr, nullptr, nullptr, nullptr);
addr_ = addr;
return true;
}
bool platform::init ()
{
sassert (fatInitDefault (), "Failed to initialize fat");

View File

@ -107,6 +107,26 @@ SockAddr::operator struct sockaddr const * () const
return reinterpret_cast<struct sockaddr const *> (&m_addr);
}
bool SockAddr::setPort (std::uint16_t const port_)
{
switch (m_addr.ss_family)
{
case AF_INET:
reinterpret_cast<struct sockaddr_in *> (&m_addr)->sin_port = htons (port_);
return true;
#ifndef NO_IPV6
case AF_INET6:
reinterpret_cast<struct sockaddr_in6 *> (&m_addr)->sin6_port = htons (port_);
return true;
#endif
default:
std::abort ();
break;
}
}
std::uint16_t SockAddr::port () const
{
switch (m_addr.ss_family)

View File

@ -1372,7 +1372,7 @@ void updateKeyboard (HidKeyboardState const &kbState_, ImGuiIO &io_)
io_.KeySuper = kbState_.modifiers & HidKeyboardModifier_Gui;
for (int i = 0; i < 256; ++i)
io_.KeysDown[i] = kbState_.keys[i / 64] & (1 << (i % 64));
io_.KeysDown[i] = kbState_.keys[i / 64] & (1ul << (i % 64));
static enum {
INACTIVE,

View File

@ -53,13 +53,16 @@ namespace
/// \brief Whether to power backlight
bool s_backlight = true;
/// \brief Whether access point is active
bool s_activeAP = false;
/// \brief Access point SSID
std::string s_ssid;
/// \brief Applet hook cookie
AppletHookCookie s_appletHookCookie;
#ifdef CLASSIC
/// \brief Host address
in_addr_t s_addr = 0;
#else
#ifndef CLASSIC
/// \brief Texture index
enum TextureIndex
{
@ -294,7 +297,7 @@ void loadTextures ()
};
TextureInfo textureInfos[] = {
// clang-format off
// clang-format off
TextureInfo (
"romfs:/deko3d.12x12.astc.zst", DkImageFormat_RGBA_ASTC_12x12, LOGO_WIDTH, LOGO_HEIGHT),
TextureInfo (
@ -315,7 +318,7 @@ void loadTextures ()
"romfs:/wifi2_icon.rgba.zst", DkImageFormat_RGBA8_Unorm, ICON_WIDTH, ICON_HEIGHT),
TextureInfo (
"romfs:/wifi3_icon.rgba.zst", DkImageFormat_RGBA8_Unorm, ICON_WIDTH, ICON_HEIGHT)
// clang-format on
// clang-format on
};
// create memblock for transfer (large enough for the largest source file)
@ -503,28 +506,33 @@ void drawStatus ()
{
TextureIndex netIcon = AIRPLANE_ICON;
NifmInternetConnectionType type;
std::uint32_t wifiStrength;
NifmInternetConnectionStatus status;
if (R_SUCCEEDED (nifmGetInternetConnectionStatus (&type, &wifiStrength, &status)))
if (s_activeAP)
netIcon = WIFI3_ICON;
else
{
if (type == NifmInternetConnectionType_Ethernet)
NifmInternetConnectionType type;
std::uint32_t wifiStrength;
NifmInternetConnectionStatus status;
if (R_SUCCEEDED (nifmGetInternetConnectionStatus (&type, &wifiStrength, &status)))
{
if (status == NifmInternetConnectionStatus_Connected)
netIcon = ETH_ICON;
if (type == NifmInternetConnectionType_Ethernet)
{
if (status == NifmInternetConnectionStatus_Connected)
netIcon = ETH_ICON;
else
netIcon = ETH_NONE_ICON;
}
else
netIcon = ETH_NONE_ICON;
}
else
{
if (wifiStrength >= 3)
netIcon = WIFI3_ICON;
else if (wifiStrength == 2)
netIcon = WIFI3_ICON;
else if (wifiStrength == 1)
netIcon = WIFI3_ICON;
else if (wifiStrength == 0)
netIcon = WIFI_NONE_ICON;
{
if (wifiStrength >= 3)
netIcon = WIFI3_ICON;
else if (wifiStrength == 2)
netIcon = WIFI3_ICON;
else if (wifiStrength == 1)
netIcon = WIFI3_ICON;
else if (wifiStrength == 0)
netIcon = WIFI_NONE_ICON;
}
}
}
@ -547,6 +555,15 @@ void drawStatus ()
pos, ImGui::GetColorU32 (ImGuiCol_Text), freeSpace.c_str ());
}
if (s_activeAP)
{
auto const size = ImGui::CalcTextSize (s_ssid.c_str ());
auto const ssidPos = ImVec2 (
io.DisplaySize.x - style.FramePadding.x - size.x, 3 * style.FramePadding.y + size.y);
ImGui::GetForegroundDrawList ()->AddText (
ssidPos, ImGui::GetColorU32 (ImGuiCol_Text), s_ssid.c_str ());
}
{
// get current timestamp
char timeBuffer[16];
@ -598,22 +615,154 @@ bool platform::init ()
return true;
}
bool platform::enableAP (bool const enableAP_,
std::string const &ssid_,
std::string const &passphrase_)
{
if (s_activeAP == enableAP_)
return true;
if (enableAP_)
{
auto const ssidError = validateSSID (ssid_);
if (ssidError)
{
error ("Access Point: %s\n", ssidError);
return false;
}
auto const passphraseError = validatePassphrase (passphrase_);
if (passphraseError)
{
error ("Access Point: %s\n", passphraseError);
return false;
}
auto rc = lp2pInitialize (Lp2pServiceType_App);
if (R_FAILED (rc))
{
error ("lp2pInitialize: 0x%x\n", rc);
return false;
}
Lp2pGroupInfo groupInfo;
lp2pCreateGroupInfo (&groupInfo);
// set SSID
lp2pGroupInfoSetServiceName (&groupInfo, ssid_.c_str ());
// enable WPA2-PSK
s8 flags = 0;
lp2pGroupInfoSetFlags (&groupInfo, &flags, 1);
// passphrase
rc = lp2pGroupInfoSetPassphrase (&groupInfo, passphrase_.c_str ());
if (R_FAILED (rc))
{
error ("lp2pGroupInfoSetPassphrase: 0x%x\n", rc);
lp2pExit ();
return false;
}
// create group
rc = lp2pCreateGroup (&groupInfo);
if (R_FAILED (rc))
{
error ("lp2pCreateGroup: 0x%x\n", rc);
lp2pExit ();
return false;
}
rc = lp2pGetGroupInfo (&groupInfo);
if (R_FAILED (rc))
{
error ("lp2pGetGroupInfo: 0x%x\n", rc);
lp2pDestroyGroup ();
lp2pExit ();
return false;
}
s_ssid = std::string ("SSID: ") + groupInfo.service_name;
s_activeAP = true;
}
else
{
lp2pDestroyGroup ();
lp2pExit ();
s_activeAP = false;
}
return true;
}
char const *platform::validateSSID (std::string const &ssid_)
{
auto const ssid = std::string_view (ssid_).substr (0, ssid_.find_first_of ('\0'));
if (ssid.size () > 19)
return "SSID too long";
for (auto const &c : ssid)
{
if (!std::isalnum (c) && c != '-')
return "SSID can only contain alphanumeric and -";
}
return nullptr;
}
char const *platform::validatePassphrase (std::string const &passphrase_)
{
auto const passphrase =
std::string_view (passphrase_).substr (0, passphrase_.find_first_of ('\0'));
if (passphrase.size () < 8)
return "Passphrase too short";
else if (passphrase.size () > 63)
return "Passphrase too long";
return nullptr;
}
bool platform::networkVisible ()
{
if (s_activeAP)
return true;
NifmInternetConnectionType type;
std::uint32_t wifi;
NifmInternetConnectionStatus status;
if (R_FAILED (nifmGetInternetConnectionStatus (&type, &wifi, &status)))
return false;
#ifdef CLASSIC
if (!s_addr)
s_addr = gethostid ();
#endif
return status == NifmInternetConnectionStatus_Connected;
}
bool platform::networkAddress (SockAddr &addr_)
{
if (s_activeAP)
{
Lp2pIpConfig ipConfig;
auto const rc = lp2pGetIpConfig (&ipConfig);
if (R_FAILED (rc))
{
error ("lp2pGetIpConfig: 0x%x\n", rc);
return false;
}
addr_ = *reinterpret_cast<struct sockaddr_in *> (ipConfig.ip_addr);
return true;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = gethostid ();
addr_ = addr;
return true;
}
bool platform::loop ()
{
if (!appletMainLoop ())
@ -672,7 +821,7 @@ void platform::render ()
#else
ImGui::Render ();
auto &io = ImGui::GetIO ();
auto const &io = ImGui::GetIO ();
if (s_width != io.DisplaySize.x || s_height != io.DisplaySize.y)
{
@ -726,6 +875,13 @@ void platform::exit ()
if (!s_backlight)
appletSetLcdBacklightOffEnabled (false);
if (s_activeAP)
{
lp2pDestroyGroup ();
lp2pExit ();
s_activeAP = false;
}
}
///////////////////////////////////////////////////////////////////////////