Use global log instead of thread-local

This commit is contained in:
Michael Theall 2020-04-09 21:21:25 -05:00
parent 3ab7a31c90
commit 1b089068c2
7 changed files with 163 additions and 222 deletions

View File

@ -21,7 +21,6 @@
#pragma once #pragma once
#include "ftpSession.h" #include "ftpSession.h"
#include "log.h"
#include "platform.h" #include "platform.h"
#include "socket.h" #include "socket.h"
@ -70,9 +69,6 @@ private:
/// \brief Thread entry point /// \brief Thread entry point
void threadFunc (); void threadFunc ();
/// \brief Log
SharedLog m_log;
/// \brief Thread /// \brief Thread
platform::Thread m_thread; platform::Thread m_thread;

View File

@ -20,100 +20,50 @@
#pragma once #pragma once
#include "platform.h"
#include <cstdarg> #include <cstdarg>
#include <memory>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector>
class Log; /// \brief Log level
using SharedLog = std::shared_ptr<Log>; enum LogLevel
using WeakLog = std::weak_ptr<Log>;
/// \brief Log object
class Log
{ {
public: DEBUG,
/// \brief Log level INFO,
enum Level ERROR,
{ COMMAND,
DEBUG, RESPONSE,
INFO,
ERROR,
COMMAND,
RESPONSE,
};
~Log ();
/// \brief Draw log
void draw ();
/// \brief Create log
static SharedLog create ();
/// \brief Bind log
/// \param log_ Log to bind
static void bind (SharedLog log_);
/// \brief Add debug message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) static void debug (char const *fmt_, ...);
/// \brief Add info message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) static void info (char const *fmt_, ...);
/// \brief Add error message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) static void error (char const *fmt_, ...);
/// \brief Add command message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) static void command (char const *fmt_, ...);
/// \brief Add response message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) static void response (char const *fmt_, ...);
/// \brief Add log message to bound log
/// \param level_ Log level
/// \param fmt_ Message format
/// \param ap_ Message arguments
static void log (Level level_, char const *fmt_, va_list ap_);
/// \brief Add log message to bound log
/// \param level_ Log level
/// \param message_ Message to log
static void log (Level level_, std::string_view message_);
private:
Log ();
/// \brief Add log message
/// \param level_ Log level
/// \param fmt_ Message format
/// \param ap_ Message arguments
void _log (Level level_, char const *fmt_, va_list ap_);
/// \brief Log message
struct Message
{
/// \brief Parameterized constructor
/// \param level_ Log level
/// \param message_ Log message
Message (Level const level_, std::string message_)
: level (level_), message (std::move (message_))
{
}
/// \brief Log level
Level level;
/// \brief Log message
std::string message;
};
/// \brief Log messages
std::vector<Message> m_messages;
/// \brief Log lock
platform::Mutex m_lock;
}; };
/// \brief Draw log
void drawLog ();
/// \brief Add debug message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) void debug (char const *fmt_, ...);
/// \brief Add info message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) void info (char const *fmt_, ...);
/// \brief Add error message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) void error (char const *fmt_, ...);
/// \brief Add command message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) void command (char const *fmt_, ...);
/// \brief Add response message to bound log
/// \param fmt_ Message format
__attribute__ ((format (printf, 1, 2))) void response (char const *fmt_, ...);
/// \brief Add log message to bound log
/// \param level_ Log level
/// \param fmt_ Message format
/// \param ap_ Message arguments
void addLog (LogLevel level_, char const *fmt_, va_list ap_);
/// \brief Add log message to bound log
/// \param level_ Log level
/// \param message_ Message to log
void addLog (LogLevel level_, std::string_view message_);

View File

@ -140,7 +140,7 @@ void startNetwork ()
return; return;
s_socuActive = true; s_socuActive = true;
Log::info ("Wifi connected\n"); info ("Wifi connected\n");
} }
/// \brief Draw citro3d logo /// \brief Draw citro3d logo

View File

@ -21,6 +21,7 @@
#include "ftpServer.h" #include "ftpServer.h"
#include "fs.h" #include "fs.h"
#include "log.h"
#include "platform.h" #include "platform.h"
#include "imgui.h" #include "imgui.h"
@ -63,11 +64,8 @@ FtpServer::~FtpServer ()
m_thread.join (); m_thread.join ();
} }
FtpServer::FtpServer (std::uint16_t const port_) FtpServer::FtpServer (std::uint16_t const port_) : m_port (port_), m_quit (false)
: m_log (Log::create ()), m_port (port_), m_quit (false)
{ {
Log::bind (m_log);
m_thread = platform::Thread (std::bind (&FtpServer::threadFunc, this)); m_thread = platform::Thread (std::bind (&FtpServer::threadFunc, this));
} }
@ -115,7 +113,7 @@ void FtpServer::draw ()
#else #else
ImGui::BeginChild ("Logs", ImVec2 (0, 200), false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::BeginChild ("Logs", ImVec2 (0, 200), false, ImGuiWindowFlags_HorizontalScrollbar);
#endif #endif
m_log->draw (); drawLog ();
ImGui::EndChild (); ImGui::EndChild ();
#ifdef _3DS #ifdef _3DS
@ -193,7 +191,7 @@ void FtpServer::handleNetworkFound ()
m_name.resize (std::strlen (name) + 3 + 5); 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[0], "[%s]:%u", name, sockName.port ()));
Log::info ("Started server at %s\n", m_name.c_str ()); info ("Started server at %s\n", m_name.c_str ());
LOCKED (m_socket = std::move (socket)); LOCKED (m_socket = std::move (socket));
} }
@ -205,7 +203,7 @@ void FtpServer::handleNetworkLost ()
LOCKED (sock = std::move (m_socket)); LOCKED (sock = std::move (m_socket));
} }
Log::info ("Stopped server at %s\n", m_name.c_str ()); info ("Stopped server at %s\n", m_name.c_str ());
} }
void FtpServer::loop () void FtpServer::loop ()
@ -266,9 +264,6 @@ void FtpServer::loop ()
void FtpServer::threadFunc () void FtpServer::threadFunc ()
{ {
// bind log for this thread
Log::bind (m_log);
while (!m_quit) while (!m_quit)
loop (); loop ();
} }

View File

@ -368,27 +368,27 @@ UniqueFtpSession FtpSession::create (UniqueSocket commandSocket_)
bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_) bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
{ {
// poll for pending close sockets first // poll for pending close sockets first
std::vector<Socket::PollInfo> info; std::vector<Socket::PollInfo> pollInfo;
for (auto &session : sessions_) for (auto &session : sessions_)
{ {
for (auto &pending : session->m_pendingCloseSocket) for (auto &pending : session->m_pendingCloseSocket)
{ {
assert (pending.unique ()); assert (pending.unique ());
info.emplace_back (Socket::PollInfo{*pending, POLLIN, 0}); pollInfo.emplace_back (Socket::PollInfo{*pending, POLLIN, 0});
} }
} }
if (!info.empty ()) if (!pollInfo.empty ())
{ {
auto const rc = Socket::poll (info.data (), info.size (), 0ms); auto const rc = Socket::poll (pollInfo.data (), pollInfo.size (), 0ms);
if (rc < 0) if (rc < 0)
{ {
Log::error ("poll: %s\n", std::strerror (errno)); error ("poll: %s\n", std::strerror (errno));
return false; return false;
} }
else else
{ {
for (auto const &i : info) for (auto const &i : pollInfo)
{ {
if (!i.revents) if (!i.revents)
continue; continue;
@ -413,14 +413,15 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
} }
// poll for everything else // poll for everything else
info.clear (); pollInfo.clear ();
for (auto &session : sessions_) for (auto &session : sessions_)
{ {
if (session->m_commandSocket) if (session->m_commandSocket)
{ {
info.emplace_back (Socket::PollInfo{*session->m_commandSocket, POLLIN | POLLPRI, 0}); pollInfo.emplace_back (
Socket::PollInfo{*session->m_commandSocket, POLLIN | POLLPRI, 0});
if (session->m_responseBuffer.usedSize () != 0) if (session->m_responseBuffer.usedSize () != 0)
info.back ().events |= POLLOUT; pollInfo.back ().events |= POLLOUT;
} }
switch (session->m_state) switch (session->m_state)
@ -434,12 +435,12 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
{ {
assert (!session->m_port); assert (!session->m_port);
// we are waiting for a PASV connection // we are waiting for a PASV connection
info.emplace_back (Socket::PollInfo{*session->m_pasvSocket, POLLIN, 0}); pollInfo.emplace_back (Socket::PollInfo{*session->m_pasvSocket, POLLIN, 0});
} }
else else
{ {
// we are waiting to complete a PORT connection // we are waiting to complete a PORT connection
info.emplace_back (Socket::PollInfo{*session->m_dataSocket, POLLOUT, 0}); pollInfo.emplace_back (Socket::PollInfo{*session->m_dataSocket, POLLOUT, 0});
} }
break; break;
@ -448,25 +449,25 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
if (session->m_recv) if (session->m_recv)
{ {
assert (!session->m_send); assert (!session->m_send);
info.emplace_back (Socket::PollInfo{*session->m_dataSocket, POLLIN, 0}); pollInfo.emplace_back (Socket::PollInfo{*session->m_dataSocket, POLLIN, 0});
} }
else else
{ {
assert (session->m_send); assert (session->m_send);
info.emplace_back (Socket::PollInfo{*session->m_dataSocket, POLLOUT, 0}); pollInfo.emplace_back (Socket::PollInfo{*session->m_dataSocket, POLLOUT, 0});
} }
break; break;
} }
} }
if (info.empty ()) if (pollInfo.empty ())
return true; return true;
// poll for activity // poll for activity
auto const rc = Socket::poll (info.data (), info.size (), 16ms); auto const rc = Socket::poll (pollInfo.data (), pollInfo.size (), 16ms);
if (rc < 0) if (rc < 0)
{ {
Log::error ("poll: %s\n", std::strerror (errno)); error ("poll: %s\n", std::strerror (errno));
return false; return false;
} }
@ -475,7 +476,7 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
for (auto &session : sessions_) for (auto &session : sessions_)
{ {
for (auto const &i : info) for (auto const &i : pollInfo)
{ {
if (!i.revents) if (!i.revents)
continue; continue;
@ -484,7 +485,7 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
if (&i.socket.get () == session->m_commandSocket.get ()) if (&i.socket.get () == session->m_commandSocket.get ())
{ {
if (i.revents & ~(POLLIN | POLLPRI | POLLOUT)) if (i.revents & ~(POLLIN | POLLPRI | POLLOUT))
Log::debug ("Command revents 0x%X\n", i.revents); debug ("Command revents 0x%X\n", i.revents);
if (i.revents & POLLOUT) if (i.revents & POLLOUT)
session->writeResponse (); session->writeResponse ();
@ -508,7 +509,7 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
case State::DATA_CONNECT: case State::DATA_CONNECT:
if (i.revents & ~(POLLIN | POLLPRI | POLLOUT)) if (i.revents & ~(POLLIN | POLLPRI | POLLOUT))
Log::debug ("Data revents 0x%X\n", i.revents); debug ("Data revents 0x%X\n", i.revents);
if (i.revents & (POLLERR | POLLHUP)) if (i.revents & (POLLERR | POLLHUP))
{ {
@ -524,7 +525,7 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
{ {
// PORT connection completed // PORT connection completed
auto const &sockName = session->m_dataSocket->peerName (); auto const &sockName = session->m_dataSocket->peerName ();
Log::info ("Connected to [%s]:%u\n", sockName.name (), sockName.port ()); info ("Connected to [%s]:%u\n", sockName.name (), sockName.port ());
session->sendResponse ("150 Ready\r\n"); session->sendResponse ("150 Ready\r\n");
session->setState (State::DATA_TRANSFER, true, false); session->setState (State::DATA_TRANSFER, true, false);
@ -533,7 +534,7 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
case State::DATA_TRANSFER: case State::DATA_TRANSFER:
if (i.revents & ~(POLLIN | POLLPRI | POLLOUT)) if (i.revents & ~(POLLIN | POLLPRI | POLLOUT))
Log::debug ("Data revents 0x%X\n", i.revents); debug ("Data revents 0x%X\n", i.revents);
// we need to transfer data // we need to transfer data
if (i.revents & (POLLERR | POLLHUP)) if (i.revents & (POLLERR | POLLHUP))
@ -1334,7 +1335,7 @@ void FtpSession::readCommand (int const events_)
// prepare to receive data // prepare to receive data
if (m_commandBuffer.freeSize () == 0) if (m_commandBuffer.freeSize () == 0)
{ {
Log::error ("Exceeded command buffer size\n"); error ("Exceeded command buffer size\n");
closeCommand (); closeCommand ();
return; return;
} }
@ -1349,7 +1350,7 @@ void FtpSession::readCommand (int const events_)
if (rc == 0) if (rc == 0)
{ {
// peer closed connection // peer closed connection
Log::info ("Peer closed connection\n"); info ("Peer closed connection\n");
closeCommand (); closeCommand ();
return; return;
} }
@ -1385,7 +1386,7 @@ void FtpSession::readCommand (int const events_)
*delim = '\0'; *delim = '\0';
decodePath (buffer, delim - buffer); decodePath (buffer, delim - buffer);
Log::command ("%s\n", buffer); command ("%s\n", buffer);
char const *const command = buffer; char const *const command = buffer;
@ -1471,7 +1472,7 @@ void FtpSession::sendResponse (char const *fmt_, ...)
va_list ap; va_list ap;
va_start (ap, fmt_); va_start (ap, fmt_);
Log::log (Log::RESPONSE, fmt_, ap); addLog (RESPONSE, fmt_, ap);
va_end (ap); va_end (ap);
va_start (ap, fmt_); va_start (ap, fmt_);
@ -1480,14 +1481,14 @@ void FtpSession::sendResponse (char const *fmt_, ...)
if (rc < 0) if (rc < 0)
{ {
Log::error ("vsnprintf: %s\n", std::strerror (errno)); error ("vsnprintf: %s\n", std::strerror (errno));
closeCommand (); closeCommand ();
return; return;
} }
if (static_cast<std::size_t> (rc) > size) if (static_cast<std::size_t> (rc) > size)
{ {
Log::error ("Not enough space for response\n"); error ("Not enough space for response\n");
closeCommand (); closeCommand ();
return; return;
} }
@ -1512,14 +1513,14 @@ void FtpSession::sendResponse (std::string_view const response_)
if (!m_commandSocket) if (!m_commandSocket)
return; return;
Log::log (Log::RESPONSE, response_); addLog (RESPONSE, response_);
auto const buffer = m_responseBuffer.freeArea (); auto const buffer = m_responseBuffer.freeArea ();
auto const size = m_responseBuffer.freeSize (); auto const size = m_responseBuffer.freeSize ();
if (response_.size () > size) if (response_.size () > size)
{ {
Log::error ("Not enough space for response\n"); error ("Not enough space for response\n");
closeCommand (); closeCommand ();
return; return;
} }
@ -1616,7 +1617,7 @@ bool FtpSession::listTransfer ()
std::uint64_t mtime = 0; std::uint64_t mtime = 0;
auto const rc = sdmc_getmtime (fullPath.c_str (), &mtime); auto const rc = sdmc_getmtime (fullPath.c_str (), &mtime);
if (rc != 0) if (rc != 0)
Log::error ("sdmc_getmtime %s 0x%lx\n", fullPath.c_str (), rc); error ("sdmc_getmtime %s 0x%lx\n", fullPath.c_str (), rc);
else else
st.st_mtime = mtime; st.st_mtime = mtime;
} }
@ -2084,7 +2085,7 @@ void FtpSession::PASV (char const *args_)
auto const &sockName = m_pasvSocket->sockName (); auto const &sockName = m_pasvSocket->sockName ();
std::string name = sockName.name (); std::string name = sockName.name ();
auto const port = sockName.port (); auto const port = sockName.port ();
Log::info ("Listening on [%s]:%u\n", name.c_str (), port); info ("Listening on [%s]:%u\n", name.c_str (), port);
// send the address in the ftp format // send the address in the ftp format
for (auto &c : name) for (auto &c : name)

View File

@ -20,9 +20,12 @@
#include "log.h" #include "log.h"
#include "platform.h"
#include "imgui.h" #include "imgui.h"
#include <mutex> #include <mutex>
#include <vector>
namespace namespace
{ {
@ -34,44 +37,59 @@ constexpr auto MAX_LOGS = 250;
constexpr auto MAX_LOGS = 10000; constexpr auto MAX_LOGS = 10000;
#endif #endif
/// \brief Bound log
thread_local WeakLog s_log;
/// \brief Message prefix /// \brief Message prefix
static char const *const s_prefix[] = { static char const *const s_prefix[] = {
[Log::DEBUG] = "[DEBUG]", [DEBUG] = "[DEBUG]",
[Log::INFO] = "[INFO]", [INFO] = "[INFO]",
[Log::ERROR] = "[ERROR]", [ERROR] = "[ERROR]",
[Log::COMMAND] = "[COMMAND]", [COMMAND] = "[COMMAND]",
[Log::RESPONSE] = "[RESPONSE]", [RESPONSE] = "[RESPONSE]",
}; };
/// \brief Log message
struct Message
{
/// \brief Parameterized constructor
/// \param level_ Log level
/// \param message_ Log message
Message (LogLevel const level_, std::string message_)
: level (level_), message (std::move (message_))
{
}
/// \brief Log level
LogLevel level;
/// \brief Log message
std::string message;
};
/// \brief Log messages
std::vector<Message> s_messages;
/// \brief Log lock
platform::Mutex s_lock;
} }
/////////////////////////////////////////////////////////////////////////// void drawLog ()
Log::~Log () = default;
Log::Log () = default;
void Log::draw ()
{ {
auto const lock = std::scoped_lock (m_lock); auto const lock = std::scoped_lock (s_lock);
if (m_messages.size () > MAX_LOGS) if (s_messages.size () > MAX_LOGS)
{ {
auto const begin = std::begin (m_messages); auto const begin = std::begin (s_messages);
auto const end = std::next (begin, m_messages.size () - MAX_LOGS); auto const end = std::next (begin, s_messages.size () - MAX_LOGS);
m_messages.erase (begin, end); s_messages.erase (begin, end);
} }
static ImVec4 const s_colors[] = { static ImVec4 const s_colors[] = {
[Log::DEBUG] = ImVec4 (1.0f, 1.0f, 0.4f, 1.0f), // yellow [DEBUG] = ImVec4 (1.0f, 1.0f, 0.4f, 1.0f), // yellow
[Log::INFO] = ImVec4 (1.0f, 1.0f, 1.0f, 1.0f), // white [INFO] = ImVec4 (1.0f, 1.0f, 1.0f, 1.0f), // white
[Log::ERROR] = ImVec4 (1.0f, 0.4f, 0.4f, 1.0f), // red [ERROR] = ImVec4 (1.0f, 0.4f, 0.4f, 1.0f), // red
[Log::COMMAND] = ImVec4 (0.4f, 1.0f, 0.4f, 1.0f), // green [COMMAND] = ImVec4 (0.4f, 1.0f, 0.4f, 1.0f), // green
[Log::RESPONSE] = ImVec4 (0.4f, 1.0f, 1.0f, 1.0f), // cyan [RESPONSE] = ImVec4 (0.4f, 1.0f, 1.0f, 1.0f), // cyan
}; };
for (auto const &message : m_messages) for (auto const &message : s_messages)
{ {
ImGui::PushStyleColor (ImGuiCol_Text, s_colors[message.level]); ImGui::PushStyleColor (ImGuiCol_Text, s_colors[message.level]);
ImGui::TextUnformatted (s_prefix[message.level]); ImGui::TextUnformatted (s_prefix[message.level]);
@ -85,98 +103,80 @@ void Log::draw ()
ImGui::SetScrollHereY (1.0f); ImGui::SetScrollHereY (1.0f);
} }
SharedLog Log::create () void debug (char const *const fmt_, ...)
{
return std::shared_ptr<Log> (new Log ());
}
void Log::bind (SharedLog log_)
{
s_log = log_;
}
void Log::debug (char const *const fmt_, ...)
{ {
#ifndef NDEBUG #ifndef NDEBUG
va_list ap; va_list ap;
va_start (ap, fmt_); va_start (ap, fmt_);
log (DEBUG, fmt_, ap); addLog (DEBUG, fmt_, ap);
va_end (ap); va_end (ap);
#endif #endif
} }
void Log::info (char const *const fmt_, ...) void info (char const *const fmt_, ...)
{ {
va_list ap; va_list ap;
va_start (ap, fmt_); va_start (ap, fmt_);
log (INFO, fmt_, ap); addLog (INFO, fmt_, ap);
va_end (ap); va_end (ap);
} }
void Log::error (char const *const fmt_, ...) void error (char const *const fmt_, ...)
{ {
va_list ap; va_list ap;
va_start (ap, fmt_); va_start (ap, fmt_);
log (ERROR, fmt_, ap); addLog (ERROR, fmt_, ap);
va_end (ap); va_end (ap);
} }
void Log::command (char const *const fmt_, ...) void command (char const *const fmt_, ...)
{ {
va_list ap; va_list ap;
va_start (ap, fmt_); va_start (ap, fmt_);
log (COMMAND, fmt_, ap); addLog (COMMAND, fmt_, ap);
va_end (ap); va_end (ap);
} }
void Log::response (char const *const fmt_, ...) void response (char const *const fmt_, ...)
{ {
va_list ap; va_list ap;
va_start (ap, fmt_); va_start (ap, fmt_);
log (RESPONSE, fmt_, ap); addLog (RESPONSE, fmt_, ap);
va_end (ap); va_end (ap);
} }
void Log::log (Level const level_, char const *const fmt_, va_list ap_) void addLog (LogLevel const level_, char const *const fmt_, va_list ap_)
{ {
#ifdef NDEBUG #ifdef NDEBUG
if (level_ == DEBUG) if (level_ == DEBUG)
return; return;
#endif #endif
auto log = s_log.lock ();
if (!log)
return;
thread_local static char buffer[1024]; thread_local static char buffer[1024];
std::vsnprintf (buffer, sizeof (buffer), fmt_, ap_); std::vsnprintf (buffer, sizeof (buffer), fmt_, ap_);
buffer[sizeof (buffer) - 1] = '\0'; buffer[sizeof (buffer) - 1] = '\0';
auto const lock = std::scoped_lock (log->m_lock); auto const lock = std::scoped_lock (s_lock);
#ifndef NDEBUG #ifndef NDEBUG
std::fprintf (stderr, "%s", s_prefix[level_]); std::fprintf (stderr, "%s", s_prefix[level_]);
std::fputs (buffer, stderr); std::fputs (buffer, stderr);
#endif #endif
log->m_messages.emplace_back (level_, buffer); s_messages.emplace_back (level_, buffer);
} }
void Log::log (Level const level_, std::string_view const message_) void addLog (LogLevel const level_, std::string_view const message_)
{ {
#ifdef NDEBUG #ifdef NDEBUG
if (level_ == DEBUG) if (level_ == DEBUG)
return; return;
#endif #endif
auto log = s_log.lock ();
if (!log)
return;
auto msg = std::string (message_); auto msg = std::string (message_);
for (auto &c : msg) for (auto &c : msg)
{ {
@ -185,10 +185,10 @@ void Log::log (Level const level_, std::string_view const message_)
c = '?'; c = '?';
} }
auto const lock = std::scoped_lock (log->m_lock); auto const lock = std::scoped_lock (s_lock);
#ifndef NDEBUG #ifndef NDEBUG
std::fprintf (stderr, "%s", s_prefix[level_]); std::fprintf (stderr, "%s", s_prefix[level_]);
std::fwrite (msg.data (), 1, msg.size (), stderr); std::fwrite (msg.data (), 1, msg.size (), stderr);
#endif #endif
log->m_messages.emplace_back (level_, msg); s_messages.emplace_back (level_, msg);
} }

View File

@ -37,13 +37,13 @@
Socket::~Socket () Socket::~Socket ()
{ {
if (m_listening) if (m_listening)
Log::info ("Stop listening on [%s]:%u\n", m_sockName.name (), m_sockName.port ()); info ("Stop listening on [%s]:%u\n", m_sockName.name (), m_sockName.port ());
if (m_connected) if (m_connected)
Log::info ("Closing connection to [%s]:%u\n", m_peerName.name (), m_peerName.port ()); info ("Closing connection to [%s]:%u\n", m_peerName.name (), m_peerName.port ());
if (::close (m_fd) != 0) if (::close (m_fd) != 0)
Log::error ("close: %s\n", std::strerror (errno)); error ("close: %s\n", std::strerror (errno));
} }
Socket::Socket (int const fd_) : m_fd (fd_), m_listening (false), m_connected (false) Socket::Socket (int const fd_) : m_fd (fd_), m_listening (false), m_connected (false)
@ -67,11 +67,11 @@ UniqueSocket Socket::accept ()
auto const fd = ::accept (m_fd, addr, &addrLen); auto const fd = ::accept (m_fd, addr, &addrLen);
if (fd < 0) if (fd < 0)
{ {
Log::error ("accept: %s\n", std::strerror (errno)); error ("accept: %s\n", std::strerror (errno));
return nullptr; return nullptr;
} }
Log::info ("Accepted connection from [%s]:%u\n", addr.name (), addr.port ()); info ("Accepted connection from [%s]:%u\n", addr.name (), addr.port ());
return UniqueSocket (new Socket (fd, m_sockName, addr)); return UniqueSocket (new Socket (fd, m_sockName, addr));
} }
@ -79,7 +79,7 @@ int Socket::atMark ()
{ {
auto const rc = ::sockatmark (m_fd); auto const rc = ::sockatmark (m_fd);
if (rc < 0) if (rc < 0)
Log::error ("sockatmark: %s\n", std::strerror (errno)); error ("sockatmark: %s\n", std::strerror (errno));
return rc; return rc;
} }
@ -91,7 +91,7 @@ bool Socket::bind (SockAddr const &addr_)
case AF_INET: case AF_INET:
if (::bind (m_fd, addr_, sizeof (struct sockaddr_in)) != 0) if (::bind (m_fd, addr_, sizeof (struct sockaddr_in)) != 0)
{ {
Log::error ("bind: %s\n", std::strerror (errno)); error ("bind: %s\n", std::strerror (errno));
return false; return false;
} }
break; break;
@ -100,7 +100,7 @@ bool Socket::bind (SockAddr const &addr_)
case AF_INET6: case AF_INET6:
if (::bind (m_fd, addr_, sizeof (struct sockaddr_in6)) != 0) if (::bind (m_fd, addr_, sizeof (struct sockaddr_in6)) != 0)
{ {
Log::error ("bind: %s\n", std::strerror (errno)); error ("bind: %s\n", std::strerror (errno));
return false; return false;
} }
break; break;
@ -108,7 +108,7 @@ bool Socket::bind (SockAddr const &addr_)
default: default:
errno = EINVAL; errno = EINVAL;
Log::error ("bind: %s\n", std::strerror (errno)); error ("bind: %s\n", std::strerror (errno));
break; break;
} }
@ -117,7 +117,7 @@ bool Socket::bind (SockAddr const &addr_)
// get socket name due to request for ephemeral port // get socket name due to request for ephemeral port
socklen_t addrLen = sizeof (struct sockaddr_storage); socklen_t addrLen = sizeof (struct sockaddr_storage);
if (::getsockname (m_fd, m_sockName, &addrLen) != 0) if (::getsockname (m_fd, m_sockName, &addrLen) != 0)
Log::error ("getsockname: %s\n", std::strerror (errno)); error ("getsockname: %s\n", std::strerror (errno));
} }
else else
m_sockName = addr_; m_sockName = addr_;
@ -130,19 +130,19 @@ bool Socket::connect (SockAddr const &addr_)
if (::connect (m_fd, addr_, sizeof (struct sockaddr_storage)) != 0) if (::connect (m_fd, addr_, sizeof (struct sockaddr_storage)) != 0)
{ {
if (errno != EINPROGRESS) if (errno != EINPROGRESS)
Log::error ("connect: %s\n", std::strerror (errno)); error ("connect: %s\n", std::strerror (errno));
else else
{ {
m_peerName = addr_; m_peerName = addr_;
m_connected = true; m_connected = true;
Log::info ("Connecting to [%s]:%u\n", addr_.name (), addr_.port ()); info ("Connecting to [%s]:%u\n", addr_.name (), addr_.port ());
} }
return false; return false;
} }
m_peerName = addr_; m_peerName = addr_;
m_connected = true; m_connected = true;
Log::info ("Connected to [%s]:%u\n", addr_.name (), addr_.port ()); info ("Connected to [%s]:%u\n", addr_.name (), addr_.port ());
return true; return true;
} }
@ -150,7 +150,7 @@ bool Socket::listen (int const backlog_)
{ {
if (::listen (m_fd, backlog_) != 0) if (::listen (m_fd, backlog_) != 0)
{ {
Log::error ("listen: %s\n", std::strerror (errno)); error ("listen: %s\n", std::strerror (errno));
return false; return false;
} }
@ -162,7 +162,7 @@ bool Socket::shutdown (int const how_)
{ {
if (::shutdown (m_fd, how_) != 0) if (::shutdown (m_fd, how_) != 0)
{ {
Log::info ("shutdown: %s\n", std::strerror (errno)); info ("shutdown: %s\n", std::strerror (errno));
return false; return false;
} }
@ -177,7 +177,7 @@ bool Socket::setLinger (bool const enable_, std::chrono::seconds const time_)
if (::setsockopt (m_fd, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger)) != 0) if (::setsockopt (m_fd, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger)) != 0)
{ {
Log::error ("setsockopt(SO_LINGER, %s, %lus): %s\n", error ("setsockopt(SO_LINGER, %s, %lus): %s\n",
enable_ ? "on" : "off", enable_ ? "on" : "off",
static_cast<unsigned long> (time_.count ()), static_cast<unsigned long> (time_.count ()),
std::strerror (errno)); std::strerror (errno));
@ -192,7 +192,7 @@ bool Socket::setNonBlocking (bool const nonBlocking_)
auto flags = ::fcntl (m_fd, F_GETFL, 0); auto flags = ::fcntl (m_fd, F_GETFL, 0);
if (flags == -1) if (flags == -1)
{ {
Log::error ("fcntl(F_GETFL): %s\n", std::strerror (errno)); error ("fcntl(F_GETFL): %s\n", std::strerror (errno));
return false; return false;
} }
@ -203,7 +203,7 @@ bool Socket::setNonBlocking (bool const nonBlocking_)
if (::fcntl (m_fd, F_SETFL, flags) != 0) if (::fcntl (m_fd, F_SETFL, flags) != 0)
{ {
Log::error ("fcntl(F_SETFL, %d): %s\n", flags, std::strerror (errno)); error ("fcntl(F_SETFL, %d): %s\n", flags, std::strerror (errno));
return false; return false;
} }
@ -215,8 +215,7 @@ bool Socket::setReuseAddress (bool const reuse_)
int reuse = reuse_; int reuse = reuse_;
if (::setsockopt (m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse)) != 0) if (::setsockopt (m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse)) != 0)
{ {
Log::error ( error ("setsockopt(SO_REUSEADDR, %s): %s\n", reuse_ ? "yes" : "no", std::strerror (errno));
"setsockopt(SO_REUSEADDR, %s): %s\n", reuse_ ? "yes" : "no", std::strerror (errno));
return false; return false;
} }
@ -228,7 +227,7 @@ bool Socket::setRecvBufferSize (std::size_t const size_)
int size = size_; int size = size_;
if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) != 0) if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) != 0)
{ {
Log::error ("setsockopt(SO_RCVBUF, %zu): %s\n", size_, std::strerror (errno)); error ("setsockopt(SO_RCVBUF, %zu): %s\n", size_, std::strerror (errno));
return false; return false;
} }
@ -240,7 +239,7 @@ bool Socket::setSendBufferSize (std::size_t const size_)
int size = size_; int size = size_;
if (::setsockopt (m_fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) != 0) if (::setsockopt (m_fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) != 0)
{ {
Log::error ("setsockopt(SO_SNDBUF, %zu): %s\n", size_, std::strerror (errno)); error ("setsockopt(SO_SNDBUF, %zu): %s\n", size_, std::strerror (errno));
return false; return false;
} }
@ -253,7 +252,7 @@ ssize_t Socket::read (void *const buffer_, std::size_t const size_, bool const o
assert (size_); assert (size_);
auto const rc = ::recv (m_fd, buffer_, size_, oob_ ? MSG_OOB : 0); auto const rc = ::recv (m_fd, buffer_, size_, oob_ ? MSG_OOB : 0);
if (rc < 0 && errno != EWOULDBLOCK) if (rc < 0 && errno != EWOULDBLOCK)
Log::error ("recv: %s\n", std::strerror (errno)); error ("recv: %s\n", std::strerror (errno));
return rc; return rc;
} }
@ -273,7 +272,7 @@ ssize_t Socket::write (void const *const buffer_, std::size_t const size_)
assert (size_); assert (size_);
auto const rc = ::send (m_fd, buffer_, size_, 0); auto const rc = ::send (m_fd, buffer_, size_, 0);
if (rc < 0 && errno != EWOULDBLOCK) if (rc < 0 && errno != EWOULDBLOCK)
Log::error ("send: %s\n", std::strerror (errno)); error ("send: %s\n", std::strerror (errno));
return rc; return rc;
} }
@ -302,7 +301,7 @@ UniqueSocket Socket::create ()
auto const fd = ::socket (AF_INET, SOCK_STREAM, 0); auto const fd = ::socket (AF_INET, SOCK_STREAM, 0);
if (fd < 0) if (fd < 0)
{ {
Log::error ("socket: %s\n", std::strerror (errno)); error ("socket: %s\n", std::strerror (errno));
return nullptr; return nullptr;
} }
@ -327,7 +326,7 @@ int Socket::poll (PollInfo *const info_,
auto const rc = ::poll (pfd.get (), count_, timeout_.count ()); auto const rc = ::poll (pfd.get (), count_, timeout_.count ());
if (rc < 0) if (rc < 0)
{ {
Log::error ("poll: %s\n", std::strerror (errno)); error ("poll: %s\n", std::strerror (errno));
return rc; return rc;
} }