#include "pch.h" #include "log.h" LogRemote LogRemote::I; static size_t data_handler(void *contents, size_t size, size_t nmemb, void *userp) { auto buffer = reinterpret_cast(userp); buffer->append((char*)contents, size * nmemb); return size * nmemb; } void LogRemote::start() { if (m_running || m_error) return; // already running m_running = true; m_thread = std::thread([&] { net_init(); auto session_string = net_request("/start"); m_session = atoi(session_string.c_str()); while (m_running && !m_error) { auto m = m_mq.Get(); auto escaped = curl_easy_escape(curl, m.c_str(), (int)m.size()); auto data = std::make_unique(m.size() + 64); int sz = snprintf(data.get(), m.size() + 64, "session=%d&m=%s", m_session, escaped); curl_free(escaped); net_request("/log", std::string(data.get(), sz)); } net_close(); LOG("NET thread loop exit"); }); } void LogRemote::net_init() { if (!(curl = curl_easy_init())) return; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &this->readBuffer); //curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, data_handler); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); } std::string LogRemote::net_request(std::string cmd, std::string data /*= ""*/) { readBuffer.clear(); curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); auto url = m_url + cmd; curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); res = curl_easy_perform(curl); if (res != CURLcode::CURLE_OK) { LOG("NET error, closed"); m_running = false; m_error = true; } return readBuffer; } void LogRemote::net_close() { if (curl) curl_easy_cleanup(curl); curl = nullptr; m_running = false; } void LogRemote::log(const char* format, ...) { static char buffer[4096]; va_list arglist; va_start(arglist, format); int n = vsnprintf(buffer, sizeof(buffer), format, arglist); va_end(arglist); m_mq.Post(std::string(buffer, n)); } void LogRemote::log(const wchar_t* format, ...) { static wchar_t buffer[4096]; va_list arglist; va_start(arglist, format); int n = vswprintf(buffer, sizeof(buffer)/sizeof(wchar_t), format, arglist); va_end(arglist); std::wstring string_to_convert(buffer, n); //setup converter // using convert_type = std::codecvt_utf8; // std::wstring_convert converter; mbstate_t st = {}; std::string converted; converted.reserve(string_to_convert.size()); const wchar_t * wptr = string_to_convert.c_str(); std::wcsrtombs((char*)converted.data(), &wptr, converted.capacity(), &st); //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr) //std::string converted_str = converter.to_bytes(string_to_convert); m_mq.Post(std::move(converted)); } LogRemote::~LogRemote() { m_running = false; m_mq.UnlockGetters(); if (m_thread.joinable()) m_thread.join(); }