diff options
Diffstat (limited to 'src/OSSupport')
38 files changed, 1328 insertions, 1166 deletions
diff --git a/src/OSSupport/AtomicUniquePtr.h b/src/OSSupport/AtomicUniquePtr.h index 92debbac6..b1867ac1a 100644 --- a/src/OSSupport/AtomicUniquePtr.h +++ b/src/OSSupport/AtomicUniquePtr.h @@ -4,41 +4,38 @@ /** An RAII wrapper for std::atomic<T*>. */ -template <typename T> -class cAtomicUniquePtr +template <typename T> class cAtomicUniquePtr { -public: + public: static_assert(!std::is_array<T>::value, "cAtomicUniquePtr does not support arrays"); DISALLOW_COPY_AND_ASSIGN(cAtomicUniquePtr); - cAtomicUniquePtr() noexcept: + cAtomicUniquePtr() noexcept : m_Ptr(nullptr) { } - cAtomicUniquePtr(std::unique_ptr<T> a_Ptr) noexcept: + cAtomicUniquePtr(std::unique_ptr<T> a_Ptr) noexcept : m_Ptr(a_Ptr.release()) { } - cAtomicUniquePtr & operator = (std::unique_ptr<T> a_Ptr) noexcept + cAtomicUniquePtr & operator=(std::unique_ptr<T> a_Ptr) noexcept { store(std::move(a_Ptr)); return *this; } - ~cAtomicUniquePtr() noexcept - { - delete load(); - } + ~cAtomicUniquePtr() noexcept { delete load(); } - operator T * () const noexcept - { - return load(); - } + operator T *() const noexcept { return load(); } - bool compare_exchange_weak(T *& a_Expected, std::unique_ptr<T> && a_Desired, std::memory_order a_Order = std::memory_order_seq_cst) noexcept + bool compare_exchange_weak( + T *& a_Expected, + std::unique_ptr<T> && a_Desired, + std::memory_order a_Order = std::memory_order_seq_cst + ) noexcept { bool DidExchange = m_Ptr.compare_exchange_weak(a_Expected, a_Desired.get(), a_Order); if (DidExchange) @@ -49,7 +46,11 @@ public: return DidExchange; } - bool compare_exchange_strong(T *& a_Expected, std::unique_ptr<T> && a_Desired, std::memory_order a_Order = std::memory_order_seq_cst) noexcept + bool compare_exchange_strong( + T *& a_Expected, + std::unique_ptr<T> && a_Desired, + std::memory_order a_Order = std::memory_order_seq_cst + ) noexcept { bool DidExchange = m_Ptr.compare_exchange_strong(a_Expected, a_Desired.get(), a_Order); if (DidExchange) @@ -60,15 +61,15 @@ public: return DidExchange; } - std::unique_ptr<T> exchange(std::unique_ptr<T> a_Ptr, std::memory_order a_Order = std::memory_order_seq_cst) noexcept + std::unique_ptr<T> exchange( + std::unique_ptr<T> a_Ptr, + std::memory_order a_Order = std::memory_order_seq_cst + ) noexcept { - return std::unique_ptr<T>{ m_Ptr.exchange(a_Ptr.release(), a_Order) }; + return std::unique_ptr<T> {m_Ptr.exchange(a_Ptr.release(), a_Order)}; } - T * load(std::memory_order a_Order = std::memory_order_seq_cst) const noexcept - { - return m_Ptr.load(a_Order); - } + T * load(std::memory_order a_Order = std::memory_order_seq_cst) const noexcept { return m_Ptr.load(a_Order); } void store(std::unique_ptr<T> a_Ptr, std::memory_order a_Order = std::memory_order_seq_cst) noexcept { @@ -76,6 +77,6 @@ public: delete m_Ptr.exchange(a_Ptr.release(), a_Order); } -private: - std::atomic<T*> m_Ptr; + private: + std::atomic<T *> m_Ptr; }; diff --git a/src/OSSupport/ConsoleSignalHandler.h b/src/OSSupport/ConsoleSignalHandler.h index 23e63d555..ee877ba3e 100644 --- a/src/OSSupport/ConsoleSignalHandler.h +++ b/src/OSSupport/ConsoleSignalHandler.h @@ -33,14 +33,13 @@ static void NonCtrlHandler(int a_Signal) { PrintStackTrace(); - LOGERROR( - "Failure report: \n\n" - " :( | Cuberite has encountered an error and needs to close\n" - " | SIGSEGV: Segmentation fault\n" - " |\n" + LOGERROR("Failure report: \n\n" + " :( | Cuberite has encountered an error and needs to close\n" + " | SIGSEGV: Segmentation fault\n" + " |\n" #ifdef BUILD_ID - " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n" - " | from commit " BUILD_COMMIT_ID "\n" + " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n" + " | from commit " BUILD_COMMIT_ID "\n" #endif ); @@ -54,14 +53,13 @@ static void NonCtrlHandler(int a_Signal) { PrintStackTrace(); - LOGERROR( - "Failure report: \n\n" - " :( | Cuberite has encountered an error and needs to close\n" - " | SIGABRT: Server self-terminated due to an internal fault\n" - " |\n" + LOGERROR("Failure report: \n\n" + " :( | Cuberite has encountered an error and needs to close\n" + " | SIGABRT: Server self-terminated due to an internal fault\n" + " |\n" #ifdef BUILD_ID - " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n" - " | from commit " BUILD_COMMIT_ID "\n" + " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n" + " | from commit " BUILD_COMMIT_ID "\n" #endif ); @@ -110,21 +108,21 @@ static BOOL CtrlHandler(DWORD fdwCtrlType) namespace ConsoleSignalHandler { - static void Register() - { - std::signal(SIGSEGV, NonCtrlHandler); - std::signal(SIGTERM, NonCtrlHandler); - std::signal(SIGINT, NonCtrlHandler); - std::signal(SIGABRT, NonCtrlHandler); +static void Register() +{ + std::signal(SIGSEGV, NonCtrlHandler); + std::signal(SIGTERM, NonCtrlHandler); + std::signal(SIGINT, NonCtrlHandler); + std::signal(SIGABRT, NonCtrlHandler); #ifdef SIGABRT_COMPAT - std::signal(SIGABRT_COMPAT, NonCtrlHandler); + std::signal(SIGABRT_COMPAT, NonCtrlHandler); #endif #ifdef SIGPIPE - std::signal(SIGPIPE, SIG_IGN); // Ignore (PR #2487). + std::signal(SIGPIPE, SIG_IGN); // Ignore (PR #2487). #endif #ifdef _WIN32 - SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE); + SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE); #endif - } -}; +} +}; // namespace ConsoleSignalHandler diff --git a/src/OSSupport/CriticalSection.cpp b/src/OSSupport/CriticalSection.cpp index 27284acb0..d902e3268 100644 --- a/src/OSSupport/CriticalSection.cpp +++ b/src/OSSupport/CriticalSection.cpp @@ -9,7 +9,7 @@ //////////////////////////////////////////////////////////////////////////////// // cCriticalSection: -cCriticalSection::cCriticalSection(): +cCriticalSection::cCriticalSection() : m_RecursionCount(0) { } @@ -63,9 +63,8 @@ bool cCriticalSection::IsLockedByCurrentThread(void) //////////////////////////////////////////////////////////////////////////////// // cCSLock -cCSLock::cCSLock(cCriticalSection * a_CS) - : m_CS(a_CS) - , m_IsLocked(false) +cCSLock::cCSLock(cCriticalSection * a_CS) : + m_CS(a_CS), m_IsLocked(false) { Lock(); } @@ -74,9 +73,8 @@ cCSLock::cCSLock(cCriticalSection * a_CS) -cCSLock::cCSLock(cCriticalSection & a_CS) - : m_CS(&a_CS) - , m_IsLocked(false) +cCSLock::cCSLock(cCriticalSection & a_CS) : + m_CS(&a_CS), m_IsLocked(false) { Lock(); } @@ -137,7 +135,3 @@ cCSUnlock::~cCSUnlock() { m_Lock.Lock(); } - - - - diff --git a/src/OSSupport/CriticalSection.h b/src/OSSupport/CriticalSection.h index 275d1a7e8..7634e5a8c 100644 --- a/src/OSSupport/CriticalSection.h +++ b/src/OSSupport/CriticalSection.h @@ -7,9 +7,10 @@ class cCriticalSection { - friend class cDeadlockDetect; // Allow the DeadlockDetect to read the internals, so that it may output some statistics + friend class cDeadlockDetect; // Allow the DeadlockDetect to read the internals, so that it may output some + // statistics -public: + public: void Lock(void); void Unlock(void); @@ -17,29 +18,28 @@ public: /** Returns true if the CS is currently locked. Note that since it relies on the m_RecursionCount value, it is inherently thread-unsafe, prone to false positives. - Also, due to multithreading, the state can change between this when function is evaluated and the returned value is used. - To be used in ASSERT(IsLocked()) only. */ + Also, due to multithreading, the state can change between this when function is evaluated and the returned value is + used. To be used in ASSERT(IsLocked()) only. */ bool IsLocked(void); /** Returns true if the CS is currently locked by the thread calling this function. Note that since it relies on the m_RecursionCount value, it is inherently thread-unsafe, prone to false positives. - Also, due to multithreading, the state can change between this when function is evaluated and the returned value is used. - To be used in ASSERT(IsLockedByCurrentThread()) only. */ + Also, due to multithreading, the state can change between this when function is evaluated and the returned value is + used. To be used in ASSERT(IsLockedByCurrentThread()) only. */ bool IsLockedByCurrentThread(void); -private: - + private: /** Number of times that this CS is currently locked (levels of recursion). Zero if not locked. - Note that this value should be considered true only when the CS is locked; without the lock, it is UndefinedBehavior to even read it, - but making it std::atomic would impose too much of a runtime penalty. - It is only ever read without the lock in the DeadlockDetect, where the server is terminating anyway. */ + Note that this value should be considered true only when the CS is locked; without the lock, it is UndefinedBehavior + to even read it, but making it std::atomic would impose too much of a runtime penalty. It is only ever read without + the lock in the DeadlockDetect, where the server is terminating anyway. */ int m_RecursionCount; /** ID of the thread that is currently holding the CS. - Note that this value should be considered true only when the CS is locked; without the lock, it is UndefinedBehavior to even read it, - but making it std::atomic would impose too much of a runtime penalty. - When unlocked, the value stored here has no meaning, it may be an ID of a previous holder, or it could be any garbage. - It is only ever read without the lock in the DeadlockDetect, where the server is terminating anyway. */ + Note that this value should be considered true only when the CS is locked; without the lock, it is UndefinedBehavior + to even read it, but making it std::atomic would impose too much of a runtime penalty. When unlocked, the value + stored here has no meaning, it may be an ID of a previous holder, or it could be any garbage. It is only ever read + without the lock in the DeadlockDetect, where the server is terminating anyway. */ std::thread::id m_OwningThreadID; std::recursive_mutex m_Mutex; @@ -53,12 +53,12 @@ class cCSLock { cCriticalSection * m_CS; - // Unlike a cCriticalSection, this object should be used from a single thread, therefore access to m_IsLocked is not threadsafe - // In Windows, it is an error to call cCriticalSection::Unlock() multiple times if the lock is not held, + // Unlike a cCriticalSection, this object should be used from a single thread, therefore access to m_IsLocked is not + // threadsafe In Windows, it is an error to call cCriticalSection::Unlock() multiple times if the lock is not held, // therefore we need to check this value whether we are locked or not. bool m_IsLocked; -public: + public: cCSLock(cCriticalSection * a_CS); cCSLock(cCriticalSection & a_CS); ~cCSLock(); @@ -67,9 +67,9 @@ public: void Lock(void); void Unlock(void); -private: + private: DISALLOW_COPY_AND_ASSIGN(cCSLock); -} ; +}; @@ -79,14 +79,11 @@ private: class cCSUnlock { cCSLock & m_Lock; -public: + + public: cCSUnlock(cCSLock & a_Lock); ~cCSUnlock(); -private: + private: DISALLOW_COPY_AND_ASSIGN(cCSUnlock); -} ; - - - - +}; diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp index 623357766..dc1cfbb37 100644 --- a/src/OSSupport/Event.cpp +++ b/src/OSSupport/Event.cpp @@ -24,7 +24,7 @@ void cEvent::Wait(void) { { std::unique_lock<std::mutex> Lock(m_Mutex); - m_CondVar.wait(Lock, [this](){ return m_ShouldContinue; }); + m_CondVar.wait(Lock, [this]() { return m_ShouldContinue; }); m_ShouldContinue = false; } } @@ -38,8 +38,9 @@ bool cEvent::Wait(unsigned a_TimeoutMSec) auto dst = std::chrono::system_clock::now() + std::chrono::milliseconds(a_TimeoutMSec); bool Result; { - std::unique_lock<std::mutex> Lock(m_Mutex); // We assume that this lock is acquired without much delay - we are the only user of the mutex - Result = m_CondVar.wait_until(Lock, dst, [this](){ return m_ShouldContinue; }); + std::unique_lock<std::mutex> Lock(m_Mutex + ); // We assume that this lock is acquired without much delay - we are the only user of the mutex + Result = m_CondVar.wait_until(Lock, dst, [this]() { return m_ShouldContinue; }); m_ShouldContinue = false; } return Result; @@ -70,8 +71,3 @@ void cEvent::SetAll(void) } m_CondVar.notify_all(); } - - - - - diff --git a/src/OSSupport/Event.h b/src/OSSupport/Event.h index ad4f07595..bcbb12998 100644 --- a/src/OSSupport/Event.h +++ b/src/OSSupport/Event.h @@ -16,7 +16,7 @@ class cEvent { -public: + public: cEvent(void); /** Waits until the event has been set. @@ -35,8 +35,7 @@ public: Returns true if the event was signalled, false if the timeout was hit or there was an error. */ bool Wait(unsigned a_TimeoutMSec); -private: - + private: /** Used for checking for spurious wakeups. */ bool m_ShouldContinue; @@ -45,9 +44,4 @@ private: /** The condition variable used as the Event. */ std::condition_variable m_CondVar; -} ; - - - - - +}; diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp index ba90f4038..88545af3d 100644 --- a/src/OSSupport/File.cpp +++ b/src/OSSupport/File.cpp @@ -8,9 +8,9 @@ #include "File.h" #include <sys/stat.h> #ifdef _WIN32 - #include <share.h> // for _SH_DENYWRITE +#include <share.h> // for _SH_DENYWRITE #else - #include <dirent.h> +#include <dirent.h> #endif // _WIN32 @@ -61,10 +61,10 @@ bool cFile::Open(const AString & iFileName, eMode iMode) const char * Mode = nullptr; switch (iMode) { - case fmRead: Mode = "rb"; break; - case fmWrite: Mode = "wb"; break; + case fmRead: Mode = "rb"; break; + case fmWrite: Mode = "wb"; break; case fmReadWrite: Mode = "rb+"; break; - case fmAppend: Mode = "a+"; break; + case fmAppend: Mode = "a+"; break; } if (Mode == nullptr) { @@ -72,11 +72,11 @@ bool cFile::Open(const AString & iFileName, eMode iMode) return false; } - #ifdef _WIN32 - m_File = _fsopen((iFileName).c_str(), Mode, _SH_DENYWR); - #else - m_File = fopen((iFileName).c_str(), Mode); - #endif // _WIN32 +#ifdef _WIN32 + m_File = _fsopen((iFileName).c_str(), Mode, _SH_DENYWR); +#else + m_File = fopen((iFileName).c_str(), Mode); +#endif // _WIN32 if ((m_File == nullptr) && (iMode == fmReadWrite)) { @@ -85,12 +85,11 @@ bool cFile::Open(const AString & iFileName, eMode iMode) // So now we know either the file doesn't exist or we don't have rights, no need to worry about file contents. // Simply re-open for read-writing, erasing existing contents: - #ifdef _WIN32 - m_File = _fsopen((iFileName).c_str(), "wb+", _SH_DENYWR); - #else - m_File = fopen((iFileName).c_str(), "wb+"); - #endif // _WIN32 - +#ifdef _WIN32 + m_File = _fsopen((iFileName).c_str(), "wb+", _SH_DENYWR); +#else + m_File = fopen((iFileName).c_str(), "wb+"); +#endif // _WIN32 } return (m_File != nullptr); } @@ -141,7 +140,7 @@ bool cFile::IsEOF(void) const -int cFile::Read (void * a_Buffer, size_t a_NumBytes) +int cFile::Read(void * a_Buffer, size_t a_NumBytes) { ASSERT(IsOpen()); @@ -150,7 +149,8 @@ int cFile::Read (void * a_Buffer, size_t a_NumBytes) return -1; } - return static_cast<int>(fread(a_Buffer, 1, a_NumBytes, m_File)); // fread() returns the portion of Count parameter actually read, so we need to send a_a_NumBytes as Count + return static_cast<int>(fread(a_Buffer, 1, a_NumBytes, m_File) + ); // fread() returns the portion of Count parameter actually read, so we need to send a_a_NumBytes as Count } @@ -186,7 +186,8 @@ int cFile::Write(const void * a_Buffer, size_t a_NumBytes) return -1; } - int res = static_cast<int>(fwrite(a_Buffer, 1, a_NumBytes, m_File)); // fwrite() returns the portion of Count parameter actually written, so we need to send a_NumBytes as Count + int res = static_cast<int>(fwrite(a_Buffer, 1, a_NumBytes, m_File) + ); // fwrite() returns the portion of Count parameter actually written, so we need to send a_NumBytes as Count return res; } @@ -194,7 +195,7 @@ int cFile::Write(const void * a_Buffer, size_t a_NumBytes) -long cFile::Seek (int iPosition) +long cFile::Seek(int iPosition) { ASSERT(IsOpen()); @@ -214,7 +215,7 @@ long cFile::Seek (int iPosition) -long cFile::Tell (void) const +long cFile::Tell(void) const { ASSERT(IsOpen()); @@ -283,7 +284,8 @@ int cFile::ReadRestOfFile(AString & a_Contents) auto DataSize = static_cast<size_t>(TotalSize - Position); - a_Contents.resize(DataSize); // TODO: investigate if worth hacking around std::string internals to avoid initialisation + a_Contents.resize(DataSize + ); // TODO: investigate if worth hacking around std::string internals to avoid initialisation return Read(a_Contents.data(), DataSize); } @@ -319,11 +321,11 @@ bool cFile::Delete(const AString & a_Path) bool cFile::DeleteFolder(const AString & a_FolderName) { - #ifdef _WIN32 - return (RemoveDirectoryA(a_FolderName.c_str()) != 0); - #else // _WIN32 - return (rmdir(a_FolderName.c_str()) == 0); - #endif // else _WIN32 +#ifdef _WIN32 + return (RemoveDirectoryA(a_FolderName.c_str()) != 0); +#else // _WIN32 + return (rmdir(a_FolderName.c_str()) == 0); +#endif // else _WIN32 } @@ -333,7 +335,7 @@ bool cFile::DeleteFolder(const AString & a_FolderName) bool cFile::DeleteFolderContents(const AString & a_FolderName) { auto Contents = cFile::GetFolderContents(a_FolderName); - for (const auto & item: Contents) + for (const auto & item : Contents) { // Remove the item: auto WholePath = a_FolderName + GetPathSeparator() + item; @@ -385,22 +387,22 @@ bool cFile::Rename(const AString & a_OrigFileName, const AString & a_NewFileName bool cFile::Copy(const AString & a_SrcFileName, const AString & a_DstFileName) { - #ifdef _WIN32 - return (CopyFileA(a_SrcFileName.c_str(), a_DstFileName.c_str(), FALSE) != 0); - #else - // Other OSs don't have a direct CopyFile equivalent, do it the harder way: - std::ifstream src(a_SrcFileName.c_str(), std::ios::binary); - std::ofstream dst(a_DstFileName.c_str(), std::ios::binary); - if (dst.good()) - { - dst << src.rdbuf(); - return true; - } - else - { - return false; - } - #endif +#ifdef _WIN32 + return (CopyFileA(a_SrcFileName.c_str(), a_DstFileName.c_str(), FALSE) != 0); +#else + // Other OSs don't have a direct CopyFile equivalent, do it the harder way: + std::ifstream src(a_SrcFileName.c_str(), std::ios::binary); + std::ofstream dst(a_DstFileName.c_str(), std::ios::binary); + if (dst.good()) + { + dst << src.rdbuf(); + return true; + } + else + { + return false; + } +#endif } @@ -409,13 +411,13 @@ bool cFile::Copy(const AString & a_SrcFileName, const AString & a_DstFileName) bool cFile::IsFolder(const AString & a_Path) { - #ifdef _WIN32 - DWORD FileAttrib = GetFileAttributesA(a_Path.c_str()); - return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0)); - #else - struct stat st; - return ((stat(a_Path.c_str(), &st) == 0) && S_ISDIR(st.st_mode)); - #endif +#ifdef _WIN32 + DWORD FileAttrib = GetFileAttributesA(a_Path.c_str()); + return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0)); +#else + struct stat st; + return ((stat(a_Path.c_str(), &st) == 0) && S_ISDIR(st.st_mode)); +#endif } @@ -424,13 +426,16 @@ bool cFile::IsFolder(const AString & a_Path) bool cFile::IsFile(const AString & a_Path) { - #ifdef _WIN32 - DWORD FileAttrib = GetFileAttributesA(a_Path.c_str()); - return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0)); - #else - struct stat st; - return ((stat(a_Path.c_str(), &st) == 0) && S_ISREG(st.st_mode)); - #endif +#ifdef _WIN32 + DWORD FileAttrib = GetFileAttributesA(a_Path.c_str()); + return ( + (FileAttrib != INVALID_FILE_ATTRIBUTES) && + ((FileAttrib & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0) + ); +#else + struct stat st; + return ((stat(a_Path.c_str(), &st) == 0) && S_ISREG(st.st_mode)); +#endif } @@ -453,11 +458,11 @@ long cFile::GetSize(const AString & a_FileName) bool cFile::CreateFolder(const AString & a_FolderPath) { - #ifdef _WIN32 - return (CreateDirectoryA(a_FolderPath.c_str(), nullptr) != 0); - #else - return (mkdir(a_FolderPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); - #endif +#ifdef _WIN32 + return (CreateDirectoryA(a_FolderPath.c_str(), nullptr) != 0); +#else + return (mkdir(a_FolderPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); +#endif } @@ -476,11 +481,11 @@ bool cFile::CreateFolderRecursive(const AString & a_FolderPath) auto len = a_FolderPath.length(); for (decltype(len) i = 0; i < len; i++) { - #ifdef _WIN32 +#ifdef _WIN32 if ((a_FolderPath[i] == '\\') || (a_FolderPath[i] == '/')) - #else +#else if (a_FolderPath[i] == '/') - #endif +#endif { CreateFolder(a_FolderPath.substr(0, i)); } @@ -499,69 +504,61 @@ AStringVector cFile::GetFolderContents(const AString & a_Folder) { AStringVector AllFiles; - #ifdef _WIN32 +#ifdef _WIN32 - // If the folder name doesn't contain the terminating slash / backslash, add it: - AString FileFilter = a_Folder; - if ( - !FileFilter.empty() && - (FileFilter[FileFilter.length() - 1] != '\\') && - (FileFilter[FileFilter.length() - 1] != '/') - ) - { - FileFilter.push_back('\\'); - } + // If the folder name doesn't contain the terminating slash / backslash, add it: + AString FileFilter = a_Folder; + if (!FileFilter.empty() && (FileFilter[FileFilter.length() - 1] != '\\') && + (FileFilter[FileFilter.length() - 1] != '/')) + { + FileFilter.push_back('\\'); + } - // Find all files / folders: - FileFilter.append("*.*"); - HANDLE hFind; - WIN32_FIND_DATAA FindFileData; - if ((hFind = FindFirstFileA(FileFilter.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) + // Find all files / folders: + FileFilter.append("*.*"); + HANDLE hFind; + WIN32_FIND_DATAA FindFileData; + if ((hFind = FindFirstFileA(FileFilter.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) + { + do { - do + if ((strcmp(FindFileData.cFileName, ".") == 0) || (strcmp(FindFileData.cFileName, "..") == 0)) { - if ( - (strcmp(FindFileData.cFileName, ".") == 0) || - (strcmp(FindFileData.cFileName, "..") == 0) - ) - { - continue; - } - AllFiles.push_back(FindFileData.cFileName); - } while (FindNextFileA(hFind, &FindFileData)); - FindClose(hFind); + continue; + } + AllFiles.push_back(FindFileData.cFileName); } + while (FindNextFileA(hFind, &FindFileData)); + FindClose(hFind); + } - #else // _WIN32 +#else // _WIN32 - DIR * dp; - AString Folder = a_Folder; - if (Folder.empty()) - { - Folder = "."; - } - if ((dp = opendir(Folder.c_str())) == nullptr) - { - LOGERROR("Error (%i) opening directory \"%s\"\n", errno, Folder.c_str()); - } - else + DIR * dp; + AString Folder = a_Folder; + if (Folder.empty()) + { + Folder = "."; + } + if ((dp = opendir(Folder.c_str())) == nullptr) + { + LOGERROR("Error (%i) opening directory \"%s\"\n", errno, Folder.c_str()); + } + else + { + struct dirent * dirp; + while ((dirp = readdir(dp)) != nullptr) { - struct dirent *dirp; - while ((dirp = readdir(dp)) != nullptr) + if ((strcmp(dirp->d_name, ".") == 0) || (strcmp(dirp->d_name, "..") == 0)) { - if ( - (strcmp(dirp->d_name, ".") == 0) || - (strcmp(dirp->d_name, "..") == 0) - ) - { - continue; - } - AllFiles.push_back(dirp->d_name); + continue; } - closedir(dp); + AllFiles.push_back(dirp->d_name); } + closedir(dp); + } - #endif // else _WIN32 +#endif // else _WIN32 return AllFiles; } @@ -590,17 +587,17 @@ AString cFile::ChangeFileExt(const AString & a_FileName, const AString & a_NewEx { auto res = a_FileName; - // If the path separator is the last character of the string, return the string unmodified (refers to a folder): - #if defined(_MSC_VER) - // Find either path separator - MSVC CRT accepts slashes as separators, too - auto LastPathSep = res.find_last_of("/\\"); - #elif defined(_WIN32) - // Windows with different CRTs support only the backslash separator - auto LastPathSep = res.rfind('\\'); - #else - // Linux supports only the slash separator - auto LastPathSep = res.rfind('/'); - #endif +// If the path separator is the last character of the string, return the string unmodified (refers to a folder): +#if defined(_MSC_VER) + // Find either path separator - MSVC CRT accepts slashes as separators, too + auto LastPathSep = res.find_last_of("/\\"); +#elif defined(_WIN32) + // Windows with different CRTs support only the backslash separator + auto LastPathSep = res.rfind('\\'); +#else + // Linux supports only the slash separator + auto LastPathSep = res.rfind('/'); +#endif if ((LastPathSep != AString::npos) && (LastPathSep + 1 == res.size())) { return res; @@ -608,9 +605,9 @@ AString cFile::ChangeFileExt(const AString & a_FileName, const AString & a_NewEx // Append or replace the extension: auto DotPos = res.rfind('.'); - if ( - (DotPos == AString::npos) || // No dot found - ((LastPathSep != AString::npos) && (LastPathSep > DotPos)) // Last dot is before the last path separator (-> in folder name) + if ((DotPos == AString::npos) || // No dot found + ((LastPathSep != AString::npos) && (LastPathSep > DotPos) + ) // Last dot is before the last path separator (-> in folder name) ) { // No extension, just append the new one: @@ -649,17 +646,17 @@ unsigned cFile::GetLastModificationTime(const AString & a_FileName) { return 0; } - #if defined(_WIN32) - // Windows returns times in local time already - return static_cast<unsigned>(st.st_mtime); - #elif defined(ANDROID) - // Identical to Linux below, but st_mtime is an unsigned long, so cast is needed: - auto Time = static_cast<time_t>(st.st_mtime); - return static_cast<unsigned>(mktime(localtime(&Time))); - #else - // Linux returns UTC time, convert to local timezone: - return static_cast<unsigned>(mktime(localtime(&st.st_mtime))); - #endif +#if defined(_WIN32) + // Windows returns times in local time already + return static_cast<unsigned>(st.st_mtime); +#elif defined(ANDROID) + // Identical to Linux below, but st_mtime is an unsigned long, so cast is needed: + auto Time = static_cast<time_t>(st.st_mtime); + return static_cast<unsigned>(mktime(localtime(&Time))); +#else + // Linux returns UTC time, convert to local timezone: + return static_cast<unsigned>(mktime(localtime(&st.st_mtime))); +#endif } @@ -668,11 +665,11 @@ unsigned cFile::GetLastModificationTime(const AString & a_FileName) AString cFile::GetPathSeparator() { - #ifdef _WIN32 - return "\\"; - #else - return "/"; - #endif +#ifdef _WIN32 + return "\\"; +#else + return "/"; +#endif } @@ -681,11 +678,11 @@ AString cFile::GetPathSeparator() AString cFile::GetExecutableExt() { - #ifdef _WIN32 - return ".exe"; - #else - return ""; - #endif +#ifdef _WIN32 + return ".exe"; +#else + return ""; +#endif } @@ -701,8 +698,7 @@ void cFile::Flush() -template <class StreamType> -FileStream<StreamType>::FileStream(const std::string & Path) +template <class StreamType> FileStream<StreamType>::FileStream(const std::string & Path) { // Except on failbit, which is what open sets on failure: FileStream::exceptions(FileStream::failbit | FileStream::badbit); diff --git a/src/OSSupport/File.h b/src/OSSupport/File.h index 975b78cd7..207d2a09e 100644 --- a/src/OSSupport/File.h +++ b/src/OSSupport/File.h @@ -36,26 +36,26 @@ For reading entire files into memory, just use the static cFile::ReadWholeFile() class cFile { -public: - + public: // tolua_end inline static char PathSeparator() { - #ifdef _WIN32 - return '\\'; - #else - return '/'; - #endif +#ifdef _WIN32 + return '\\'; +#else + return '/'; +#endif } /** The mode in which to open the file */ enum eMode { - fmRead, // Read-only. If the file doesn't exist, object will not be valid - fmWrite, // Write-only. If the file already exists, it will be overwritten - fmReadWrite, // Read / write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning - fmAppend // Write-only. If the file already exists cursor will be moved to the end of the file - } ; + fmRead, // Read-only. If the file doesn't exist, object will not be valid + fmWrite, // Write-only. If the file already exists, it will be overwritten + fmReadWrite, // Read / write. If the file already exists, it will be left intact; writing will overwrite the + // data from the beginning + fmAppend // Write-only. If the file already exists cursor will be moved to the end of the file + }; /** Simple constructor - creates an unopened file object, use Open() to open / create a real file */ cFile(void); @@ -71,37 +71,39 @@ public: bool IsOpen(void) const; bool IsEOF(void) const; - /** Reads up to a_NumBytes bytes into a_Buffer, returns the number of bytes actually read, or -1 on failure; asserts if not open */ + /** Reads up to a_NumBytes bytes into a_Buffer, returns the number of bytes actually read, or -1 on failure; asserts + * if not open */ int Read(void * a_Buffer, size_t a_NumBytes); - /** Reads up to a_NumBytes bytes, returns the bytes actually read, or empty string on failure; asserts if not open */ + /** Reads up to a_NumBytes bytes, returns the bytes actually read, or empty string on failure; asserts if not open + */ std::basic_string<std::byte> Read(size_t a_NumBytes); - /** Writes up to a_NumBytes bytes from a_Buffer, returns the number of bytes actually written, or -1 on failure; asserts if not open */ + /** Writes up to a_NumBytes bytes from a_Buffer, returns the number of bytes actually written, or -1 on failure; + * asserts if not open */ int Write(const void * a_Buffer, size_t a_NumBytes); - int Write(std::string_view a_String) - { - return Write(a_String.data(), a_String.size()); - } + int Write(std::string_view a_String) { return Write(a_String.data(), a_String.size()); } /** Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open */ - long Seek (int iPosition); + long Seek(int iPosition); /** Returns the current position (bytes from file start) or -1 for failure; asserts if not open */ - long Tell (void) const; + long Tell(void) const; /** Returns the size of file, in bytes, or -1 for failure; asserts if not open */ long GetSize(void) const; - /** Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error */ + /** Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error + */ int ReadRestOfFile(AString & a_Contents); /** Returns true if the file specified exists */ static bool Exists(const AString & a_FileName); // Exported in ManualBindings.cpp /** Deletes a file or a folder, returns true if successful. - Prefer to use DeleteFile or DeleteFolder, since those don't have the penalty of checking whether a_Path is a folder. */ + Prefer to use DeleteFile or DeleteFolder, since those don't have the penalty of checking whether a_Path is a folder. + */ static bool Delete(const AString & a_Path); // Exported in ManualBindings.cpp /** Deletes a file, returns true if successful. @@ -138,7 +140,8 @@ public: /** Creates a new folder with the specified name, creating its parents if needed. Path may be relative or absolute. Returns true if the folder exists at the end of the operation (either created, or already existed). - Supports only paths that use the path separator used by the current platform (MSVC CRT supports slashes for file paths, too, but this function doesn't) */ + Supports only paths that use the path separator used by the current platform (MSVC CRT supports slashes for file + paths, too, but this function doesn't) */ static bool CreateFolderRecursive(const AString & a_FolderPath); // Exported in ManualBindings.cpp /** Returns the entire contents of the specified file as a string. Returns empty string on error. */ @@ -146,7 +149,10 @@ public: /** Returns a_FileName with its extension changed to a_NewExt. a_FileName may contain path specification. */ - static AString ChangeFileExt(const AString & a_FileName, const AString & a_NewExt); // Exported in ManualBindings.cpp + static AString ChangeFileExt( + const AString & a_FileName, + const AString & a_NewExt + ); // Exported in ManualBindings.cpp /** Returns the last modification time (in current timezone) of the specified file. The value returned is in the same units as the value returned by time() function. @@ -157,7 +163,8 @@ public: // tolua_begin /** Returns the path separator used by the current platform. - Note that the platform / CRT may support additional path separators (such as slashes on Windows), these don't get reported. */ + Note that the platform / CRT may support additional path separators (such as slashes on Windows), these don't get + reported. */ static AString GetPathSeparator(); /** Returns the customary executable extension used by the current platform. */ @@ -171,20 +178,18 @@ public: /** Flushes all the bufferef output into the file (only when writing) */ void Flush(); -private: + private: FILE * m_File; -} ; // tolua_export +}; // tolua_export /** A wrapper for file streams that enables exceptions. */ -template <class StreamType> -class FileStream final : public StreamType +template <class StreamType> class FileStream final : public StreamType { -public: - + public: FileStream(const std::string & Path); FileStream(const std::string & Path, const typename FileStream::openmode Mode); }; diff --git a/src/OSSupport/GZipFile.cpp b/src/OSSupport/GZipFile.cpp index 0bf26dfed..a08fe2441 100644 --- a/src/OSSupport/GZipFile.cpp +++ b/src/OSSupport/GZipFile.cpp @@ -14,8 +14,8 @@ Compression::Result GZipFile::ReadRestOfFile(const std::string & a_FileName) { InputFileStream File(a_FileName, InputFileStream::binary); - const std::string Input{ std::istreambuf_iterator<char>(File), std::istreambuf_iterator<char>() }; - const ContiguousByteBufferView Data{ reinterpret_cast<const std::byte *>(Input.data()), Input.size() }; + const std::string Input {std::istreambuf_iterator<char>(File), std::istreambuf_iterator<char>()}; + const ContiguousByteBufferView Data {reinterpret_cast<const std::byte *>(Input.data()), Input.size()}; return Compression::Extractor().ExtractGZip(Data); } @@ -26,5 +26,6 @@ Compression::Result GZipFile::ReadRestOfFile(const std::string & a_FileName) void GZipFile::Write(const std::string & a_FileName, ContiguousByteBufferView a_Contents) { - OutputFileStream(a_FileName, OutputFileStream::binary) << Compression::Compressor().CompressGZip(a_Contents).GetStringView(); + OutputFileStream(a_FileName, OutputFileStream::binary) + << Compression::Compressor().CompressGZip(a_Contents).GetStringView(); } diff --git a/src/OSSupport/GZipFile.h b/src/OSSupport/GZipFile.h index dd4999339..9ce53ed26 100644 --- a/src/OSSupport/GZipFile.h +++ b/src/OSSupport/GZipFile.h @@ -17,9 +17,9 @@ namespace GZipFile { - /** Reads the rest of the file and returns the decompressed contents. */ - Compression::Result ReadRestOfFile(const std::string & a_FileName); +/** Reads the rest of the file and returns the decompressed contents. */ +Compression::Result ReadRestOfFile(const std::string & a_FileName); - /** Writes a_Contents into file, compressing it along the way. */ - void Write(const std::string & a_FileName, ContiguousByteBufferView a_Contents); -} ; +/** Writes a_Contents into file, compressing it along the way. */ +void Write(const std::string & a_FileName, ContiguousByteBufferView a_Contents); +}; // namespace GZipFile diff --git a/src/OSSupport/GetAddressInfoError.h b/src/OSSupport/GetAddressInfoError.h index 43869fb63..3dbefb426 100644 --- a/src/OSSupport/GetAddressInfoError.h +++ b/src/OSSupport/GetAddressInfoError.h @@ -5,25 +5,22 @@ /** Returns the readable form of a getaddressinfo type error code */ inline AString ErrorString(int a_ErrorCode) { - // Note gai_strerror is not threadsafe on windows - #ifdef _WIN32 - char ErrorStr[GAI_STRERROR_BUFFER_SIZE + 1]; +// Note gai_strerror is not threadsafe on windows +#ifdef _WIN32 + char ErrorStr[GAI_STRERROR_BUFFER_SIZE + 1]; - int MsgLen = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_MAX_WIDTH_MASK, - nullptr, - a_ErrorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - ErrorStr, - sizeof(ErrorStr) - 1, - nullptr - ); + int MsgLen = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, + nullptr, + a_ErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + ErrorStr, + sizeof(ErrorStr) - 1, + nullptr + ); - return AString(ErrorStr, MsgLen); - #else - return gai_strerror(a_ErrorCode); - #endif + return AString(ErrorStr, MsgLen); +#else + return gai_strerror(a_ErrorCode); +#endif } - diff --git a/src/OSSupport/HostnameLookup.cpp b/src/OSSupport/HostnameLookup.cpp index d86430d83..a1489c389 100644 --- a/src/OSSupport/HostnameLookup.cpp +++ b/src/OSSupport/HostnameLookup.cpp @@ -15,9 +15,8 @@ //////////////////////////////////////////////////////////////////////////////// // cHostnameLookup: -cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks): - m_Callbacks(std::move(a_Callbacks)), - m_Hostname(a_Hostname) +cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks) : + m_Callbacks(std::move(a_Callbacks)), m_Hostname(a_Hostname) { } @@ -28,24 +27,26 @@ cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveN void cHostnameLookup::Lookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks) { // Cannot use std::make_shared here, constructor is not accessible - cHostnameLookupPtr Lookup{ new cHostnameLookup(a_Hostname, std::move(a_Callbacks)) }; + cHostnameLookupPtr Lookup {new cHostnameLookup(a_Hostname, std::move(a_Callbacks))}; // Note the Lookup object is owned solely by this lambda which is destroyed after it runs - cNetworkSingleton::Get().GetLookupThread().ScheduleLookup([=]() - { - // Start the lookup: - addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_protocol = IPPROTO_TCP; - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_CANONNAME; - - addrinfo * Result; - int ErrCode = getaddrinfo(Lookup->m_Hostname.c_str(), nullptr, &hints, &Result); - - Lookup->Callback(ErrCode, Result); - }); + cNetworkSingleton::Get().GetLookupThread().ScheduleLookup( + [=]() + { + // Start the lookup: + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_protocol = IPPROTO_TCP; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + + addrinfo * Result; + int ErrCode = getaddrinfo(Lookup->m_Hostname.c_str(), nullptr, &hints, &Result); + + Lookup->Callback(ErrCode, Result); + } + ); } @@ -64,7 +65,7 @@ void cHostnameLookup::Callback(int a_ErrCode, addrinfo * a_Addr) // Call the success handler for each entry received: bool HasResolved = false; addrinfo * OrigAddr = a_Addr; - for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next) + for (; a_Addr != nullptr; a_Addr = a_Addr->ai_next) { char IP[128]; switch (a_Addr->ai_family) @@ -74,7 +75,8 @@ void cHostnameLookup::Callback(int a_ErrCode, addrinfo * a_Addr) sockaddr_in * sin = reinterpret_cast<sockaddr_in *>(a_Addr->ai_addr); if (!m_Callbacks->OnNameResolvedV4(m_Hostname, sin)) { - // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next address: + // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next + // address: HasResolved = true; continue; } @@ -86,7 +88,8 @@ void cHostnameLookup::Callback(int a_ErrCode, addrinfo * a_Addr) sockaddr_in6 * sin = reinterpret_cast<sockaddr_in6 *>(a_Addr->ai_addr); if (!m_Callbacks->OnNameResolvedV6(m_Hostname, sin)) { - // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next address: + // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next + // address: HasResolved = true; continue; } @@ -122,15 +125,8 @@ void cHostnameLookup::Callback(int a_ErrCode, addrinfo * a_Addr) //////////////////////////////////////////////////////////////////////////////// // cNetwork API: -bool cNetwork::HostnameToIP( - const AString & a_Hostname, - cNetwork::cResolveNameCallbacksPtr a_Callbacks -) +bool cNetwork::HostnameToIP(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks) { cHostnameLookup::Lookup(a_Hostname, std::move(a_Callbacks)); return true; } - - - - diff --git a/src/OSSupport/HostnameLookup.h b/src/OSSupport/HostnameLookup.h index 9189ef021..77f4a6b06 100644 --- a/src/OSSupport/HostnameLookup.h +++ b/src/OSSupport/HostnameLookup.h @@ -20,12 +20,11 @@ /** Holds information about an in-progress Hostname-to-IP lookup. */ class cHostnameLookup { -public: + public: /** Creates a lookup object and schedules the lookup. */ static void Lookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks); -protected: - + protected: /** Creates the lookup object. Doesn't start the lookup yet. */ cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks); @@ -39,8 +38,3 @@ protected: }; typedef std::shared_ptr<cHostnameLookup> cHostnameLookupPtr; typedef std::vector<cHostnameLookupPtr> cHostnameLookupPtrs; - - - - - diff --git a/src/OSSupport/IPLookup.cpp b/src/OSSupport/IPLookup.cpp index f730110b9..42bf3a92a 100644 --- a/src/OSSupport/IPLookup.cpp +++ b/src/OSSupport/IPLookup.cpp @@ -16,9 +16,8 @@ //////////////////////////////////////////////////////////////////////////////// // cIPLookup: -cIPLookup::cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks): - m_Callbacks(std::move(a_Callbacks)), - m_IP(a_IP) +cIPLookup::cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks) : + m_Callbacks(std::move(a_Callbacks)), m_IP(a_IP) { ASSERT(m_Callbacks != nullptr); } @@ -29,36 +28,41 @@ cIPLookup::cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_ void cIPLookup::Lookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks) { - cIPLookupPtr Lookup{ new cIPLookup(a_IP, std::move(a_Callbacks)) }; // Cannot use std::make_shared here, constructor is not accessible + cIPLookupPtr Lookup {new cIPLookup(a_IP, std::move(a_Callbacks)) + }; // Cannot use std::make_shared here, constructor is not accessible // Note the Lookup object is owned solely by this lambda which is destroyed after it runs - cNetworkSingleton::Get().GetLookupThread().ScheduleLookup([=]() - { - sockaddr_storage sa; - int salen = sizeof(sa); - memset(&sa, 0, sizeof(sa)); - - int ErrCode = evutil_parse_sockaddr_port(Lookup->m_IP.c_str(), reinterpret_cast<sockaddr *>(&sa), &salen); - - if (ErrCode != 0) + cNetworkSingleton::Get().GetLookupThread().ScheduleLookup( + [=]() { - LOGD("Failed to parse IP address \"%s\".", Lookup->m_IP.c_str()); - Lookup->Callback(ErrCode, nullptr); - return; + sockaddr_storage sa; + int salen = sizeof(sa); + memset(&sa, 0, sizeof(sa)); + + int ErrCode = evutil_parse_sockaddr_port(Lookup->m_IP.c_str(), reinterpret_cast<sockaddr *>(&sa), &salen); + + if (ErrCode != 0) + { + LOGD("Failed to parse IP address \"%s\".", Lookup->m_IP.c_str()); + Lookup->Callback(ErrCode, nullptr); + return; + } + + char Hostname[NI_MAXHOST]; + char ServInfo[NI_MAXSERV]; + + ErrCode = getnameinfo( + reinterpret_cast<sockaddr *>(&sa), + static_cast<socklen_t>(salen), + Hostname, + sizeof(Hostname), + ServInfo, + sizeof(ServInfo), + 0 + ); + Lookup->Callback(ErrCode, Hostname); } - - char Hostname[NI_MAXHOST]; - char ServInfo[NI_MAXSERV]; - - ErrCode = getnameinfo( - reinterpret_cast<sockaddr *>(&sa), - static_cast<socklen_t>(salen), - Hostname, sizeof(Hostname), - ServInfo, sizeof(ServInfo), - 0 - ); - Lookup->Callback(ErrCode, Hostname); - }); + ); } @@ -88,15 +92,8 @@ void cIPLookup::Callback(int a_Result, const char * a_Address) //////////////////////////////////////////////////////////////////////////////// // cNetwork API: -bool cNetwork::IPToHostName( - const AString & a_IP, - cNetwork::cResolveNameCallbacksPtr a_Callbacks -) +bool cNetwork::IPToHostName(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks) { cIPLookup::Lookup(a_IP, std::move(a_Callbacks)); return true; } - - - - diff --git a/src/OSSupport/IPLookup.h b/src/OSSupport/IPLookup.h index 4e3065f1c..f612f14ee 100644 --- a/src/OSSupport/IPLookup.h +++ b/src/OSSupport/IPLookup.h @@ -20,13 +20,11 @@ /** Holds information about an in-progress IP-to-Hostname lookup. */ class cIPLookup { -public: - + public: /** Creates a lookup object and schedules the lookup. */ static void Lookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks); -protected: - + protected: /** The callbacks to call for resolved names / errors. */ cNetwork::cResolveNameCallbacksPtr m_Callbacks; @@ -41,8 +39,3 @@ protected: }; typedef std::shared_ptr<cIPLookup> cIPLookupPtr; typedef std::vector<cIPLookupPtr> cIPLookupPtrs; - - - - - diff --git a/src/OSSupport/IsThread.cpp b/src/OSSupport/IsThread.cpp index 03ca2bfc4..23abaad3e 100644 --- a/src/OSSupport/IsThread.cpp +++ b/src/OSSupport/IsThread.cpp @@ -14,8 +14,7 @@ // cIsThread: cIsThread::cIsThread(AString && a_ThreadName) : - m_ShouldTerminate(false), - m_ThreadName(std::move(a_ThreadName)) + m_ShouldTerminate(false), m_ThreadName(std::move(a_ThreadName)) { } @@ -106,15 +105,15 @@ void cIsThread::SetThreadName() const #pragma pack(push, 8) struct THREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1 = caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1 = caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. }; #pragma pack(pop) const DWORD NAME_EXCEPTION = 0x406D1388; - const THREADNAME_INFO Name = { 0x1000, m_ThreadName.c_str(), static_cast<DWORD>(-1), 0 }; + const THREADNAME_INFO Name = {0x1000, m_ThreadName.c_str(), static_cast<DWORD>(-1), 0}; __try { diff --git a/src/OSSupport/IsThread.h b/src/OSSupport/IsThread.h index 4c2131d24..b53be5f4d 100644 --- a/src/OSSupport/IsThread.h +++ b/src/OSSupport/IsThread.h @@ -7,7 +7,8 @@ Usage: To have a new thread, declare a class descending from cIsThread. Then override its Execute() method to provide your thread processing. -In the descending class' constructor call the Start() method to start the thread once you're finished with initialization. +In the descending class' constructor call the Start() method to start the thread once you're finished with +initialization. */ @@ -22,8 +23,7 @@ In the descending class' constructor call the Start() method to start the thread class cIsThread { -public: - + public: cIsThread(AString && a_ThreadName); virtual ~cIsThread(); @@ -36,16 +36,14 @@ public: /** Returns true if the thread calling this function is the thread contained within this object. */ bool IsCurrentThread(void) const { return std::this_thread::get_id() == m_Thread.get_id(); } -protected: - + protected: /** This function, overloaded by the descendants, is called in the new thread. */ virtual void Execute(void) = 0; /** The overriden Execute() method should check this value periodically and terminate if this is true. */ std::atomic<bool> m_ShouldTerminate; -private: - + private: /** The thread object which holds the created thread for later manipulation */ std::thread m_Thread; @@ -53,13 +51,15 @@ private: AString m_ThreadName; /** The event that is used to wait with the thread's execution until the thread object is fully initialized. - This prevents the IsCurrentThread() call to fail because of a race-condition where the thread starts before m_Thread has been fully assigned. */ + This prevents the IsCurrentThread() call to fail because of a race-condition where the thread starts before m_Thread + has been fully assigned. */ cEvent m_Initialisation; /** This is the main thread entrypoint. - Wrapper for Execute() that waits for the initialization event, to prevent race conditions in thread initialization. */ + Wrapper for Execute() that waits for the initialization event, to prevent race conditions in thread initialization. + */ void Entrypoint(void); /** Sets the name of the current thread to be the name provided in m_ThreadName. */ void SetThreadName() const; -} ; +}; diff --git a/src/OSSupport/MiniDumpWriter.h b/src/OSSupport/MiniDumpWriter.h index c223fa9fb..f02b2f784 100644 --- a/src/OSSupport/MiniDumpWriter.h +++ b/src/OSSupport/MiniDumpWriter.h @@ -34,16 +34,18 @@ using MiniDumpWriteDumpFunction = decltype(&MiniDumpWriteDump); static HINSTANCE m_DbgHelp; static MiniDumpWriteDumpFunction s_WriteMiniDump; // The function in dbghlp DLL that creates dump files -static wchar_t s_DumpFileName[MAX_PATH]; // Filename of the dump file; hes to be created before the dump handler kicks in -static char s_ExceptionStack[128 * 1024]; // Substitute stack, just in case the handler kicks in because of "insufficient stack space" +static wchar_t + s_DumpFileName[MAX_PATH]; // Filename of the dump file; hes to be created before the dump handler kicks in +static char s_ExceptionStack[128 * 1024]; // Substitute stack, just in case the handler kicks in because of + // "insufficient stack space" static MINIDUMP_TYPE s_DumpFlags = MiniDumpNormal; // By default dump only the stack and some helpers -/** This function gets called just before the "program executed an illegal instruction and will be terminated" or similar. -Its purpose is to create the crashdump using the dbghlp DLLs */ +/** This function gets called just before the "program executed an illegal instruction and will be terminated" or +similar. Its purpose is to create the crashdump using the dbghlp DLLs */ static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo) { char * newStack = &s_ExceptionStack[sizeof(s_ExceptionStack) - 1]; @@ -51,19 +53,28 @@ static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a // Use the substitute stack: _asm - { + { mov oldStack, esp mov esp, newStack - } + } - MINIDUMP_EXCEPTION_INFORMATION ExcInformation; + MINIDUMP_EXCEPTION_INFORMATION ExcInformation; ExcInformation.ThreadId = GetCurrentThreadId(); ExcInformation.ExceptionPointers = a_ExceptionInfo; ExcInformation.ClientPointers = 0; // Write the dump file: - HANDLE dumpFile = CreateFile(s_DumpFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - s_WriteMiniDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, s_DumpFlags, (a_ExceptionInfo) ? &ExcInformation : nullptr, nullptr, nullptr); + HANDLE dumpFile = + CreateFile(s_DumpFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + s_WriteMiniDump( + GetCurrentProcess(), + GetCurrentProcessId(), + dumpFile, + s_DumpFlags, + (a_ExceptionInfo) ? &ExcInformation : nullptr, + nullptr, + nullptr + ); CloseHandle(dumpFile); // Revert to old stack: @@ -81,64 +92,58 @@ static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a namespace MiniDumpWriter { - static void Register() - { - // Magic code to produce dump-files on Windows if the server crashes: - - m_DbgHelp = LoadLibrary(L"DBGHELP.DLL"); - if (m_DbgHelp == INVALID_HANDLE_VALUE) - { - return; - } +static void Register() +{ + // Magic code to produce dump-files on Windows if the server crashes: - s_WriteMiniDump = (MiniDumpWriteDumpFunction)GetProcAddress(m_DbgHelp, "MiniDumpWriteDump"); - if (s_WriteMiniDump != nullptr) - { - ASSERT(swprintf(s_DumpFileName, ARRAYCOUNT(s_DumpFileName), L"crash_mcs_%x.dmp", GetCurrentProcessId()) > 0); - SetUnhandledExceptionFilter(LastChanceExceptionFilter); - } + m_DbgHelp = LoadLibrary(L"DBGHELP.DLL"); + if (m_DbgHelp == INVALID_HANDLE_VALUE) + { + return; + } - // End of dump-file magic + s_WriteMiniDump = (MiniDumpWriteDumpFunction) GetProcAddress(m_DbgHelp, "MiniDumpWriteDump"); + if (s_WriteMiniDump != nullptr) + { + ASSERT(swprintf(s_DumpFileName, ARRAYCOUNT(s_DumpFileName), L"crash_mcs_%x.dmp", GetCurrentProcessId()) > 0); + SetUnhandledExceptionFilter(LastChanceExceptionFilter); } - static void AddDumpFlags(const MiniDumpFlags a_Flags) + // End of dump-file magic +} + +static void AddDumpFlags(const MiniDumpFlags a_Flags) +{ + switch (a_Flags) { - switch (a_Flags) + case MiniDumpFlags::WithDataSegments: + { + s_DumpFlags = static_cast<MINIDUMP_TYPE>(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithDataSegs); + break; + } + case MiniDumpFlags::WithFullMemory: { - case MiniDumpFlags::WithDataSegments: - { - s_DumpFlags = static_cast<MINIDUMP_TYPE>(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithDataSegs); - break; - } - case MiniDumpFlags::WithFullMemory: - { - s_DumpFlags = static_cast<MINIDUMP_TYPE>(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithFullMemory); - break; - } + s_DumpFlags = static_cast<MINIDUMP_TYPE>(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithFullMemory); + break; } } +} - static void Unregister() - { - FreeLibrary(m_DbgHelp); - } -}; +static void Unregister() +{ + FreeLibrary(m_DbgHelp); +} +}; // namespace MiniDumpWriter #else namespace MiniDumpWriter { - static void Register() - { - } +static void Register() {} - static void AddDumpFlags(const MiniDumpFlags) - { - } +static void AddDumpFlags(const MiniDumpFlags) {} - static void Unregister() - { - } -}; +static void Unregister() {} +}; // namespace MiniDumpWriter #endif diff --git a/src/OSSupport/Network.h b/src/OSSupport/Network.h index ca31d9948..17a213a47 100644 --- a/src/OSSupport/Network.h +++ b/src/OSSupport/Network.h @@ -14,7 +14,7 @@ #ifdef __FreeBSD__ - #include <netinet/in.h> +#include <netinet/in.h> #endif @@ -42,15 +42,16 @@ class cTCPLink { friend class cNetwork; -public: + public: class cCallbacks { - public: + public: // Force a virtual destructor for all descendants: virtual ~cCallbacks() {} /** Called when the cTCPLink for the connection is created. - The callback may store the cTCPLink instance for later use, but it should remove it in OnError(), OnRemoteClosed() or right after Close(). */ + The callback may store the cTCPLink instance for later use, but it should remove it in OnError(), + OnRemoteClosed() or right after Close(). */ virtual void OnLinkCreated(cTCPLinkPtr a_Link) = 0; /** Called when there's data incoming from the remote peer. */ @@ -62,7 +63,8 @@ public: virtual void OnRemoteClosed(void) = 0; /** Called when the TLS handshake has been completed and communication can continue regularly. - Has an empty default implementation, so that link callback descendants don't need to specify TLS handlers when they don't use TLS at all. */ + Has an empty default implementation, so that link callback descendants don't need to specify TLS handlers when + they don't use TLS at all. */ virtual void OnTlsHandshakeCompleted(void) {} /** Called when an error is detected on the connection. */ @@ -75,15 +77,14 @@ public: virtual ~cTCPLink() {} /** Queues the specified data for sending to the remote peer. - Returns true on success, false on failure. Note that this success or failure only reports the queue status, not the actual data delivery. */ + Returns true on success, false on failure. Note that this success or failure only reports the queue status, not the + actual data delivery. */ virtual bool Send(const void * a_Data, size_t a_Length) = 0; /** Queues the specified data for sending to the remote peer. - Returns true on success, false on failure. Note that this success or failure only reports the queue status, not the actual data delivery. */ - bool Send(const AString & a_Data) - { - return Send(a_Data.data(), a_Data.size()); - } + Returns true on success, false on failure. Note that this success or failure only reports the queue status, not the + actual data delivery. */ + bool Send(const AString & a_Data) { return Send(a_Data.data(), a_Data.size()); } /** Returns the IP address of the local endpoint of the connection. */ virtual AString GetLocalIP(void) const = 0; @@ -134,13 +135,13 @@ public: /** Returns the callbacks that are used. */ cCallbacksPtr GetCallbacks(void) const { return m_Callbacks; } -protected: + protected: /** Callbacks to be used for the various situations. */ cCallbacksPtr m_Callbacks; /** Creates a new link, with the specified callbacks. */ - cTCPLink(cCallbacksPtr a_Callbacks): + cTCPLink(cCallbacksPtr a_Callbacks) : m_Callbacks(std::move(a_Callbacks)) { } @@ -154,8 +155,8 @@ protected: class cServerHandle { friend class cNetwork; -public: + public: // Force a virtual destructor for all descendants: virtual ~cServerHandle() {} @@ -174,11 +175,11 @@ public: /** Interface that provides methods available on UDP communication endpoints. */ class cUDPEndpoint { -public: + public: /** Interface for the callbacks for events that can happen on the endpoint. */ class cCallbacks { - public: + public: // Force a virtual destructor in all descendants: virtual ~cCallbacks() {} @@ -186,7 +187,12 @@ public: virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) = 0; /** Called when there is an incoming datagram from a remote host. */ - virtual void OnReceivedData(const char * a_Data, size_t a_Size, const AString & a_RemoteHost, UInt16 a_RemotePort) = 0; + virtual void OnReceivedData( + const char * a_Data, + size_t a_Size, + const AString & a_RemoteHost, + UInt16 a_RemotePort + ) = 0; }; @@ -211,13 +217,13 @@ public: Without this call, sending to a broadcast address using Send() may fail. */ virtual void EnableBroadcasts(void) = 0; -protected: + protected: /** The callbacks used for various events on the endpoint. */ cCallbacks & m_Callbacks; /** Creates a new instance of an endpoint, with the specified callbacks. */ - cUDPEndpoint(cCallbacks & a_Callbacks): + cUDPEndpoint(cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks) { } @@ -231,11 +237,11 @@ typedef std::shared_ptr<cUDPEndpoint> cUDPEndpointPtr; class cNetwork { -public: + public: /** Callbacks used for connecting to other servers as a client. */ class cConnectCallbacks { - public: + public: // Force a virtual destructor for all descendants: virtual ~cConnectCallbacks() {} @@ -252,7 +258,7 @@ public: /** Callbacks used when listening for incoming connections as a server. */ class cListenCallbacks { - public: + public: // Force a virtual destructor for all descendants: virtual ~cListenCallbacks() {} @@ -260,7 +266,10 @@ public: Returns the link callbacks that the server should use for the newly created link. If a nullptr is returned, the connection is dropped immediately; otherwise a new cTCPLink instance is created and OnAccepted() is called. */ - virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) = 0; + virtual cTCPLink::cCallbacksPtr OnIncomingConnection( + const AString & a_RemoteIPAddress, + UInt16 a_RemotePort + ) = 0; /** Called when the TCP server created with Listen() creates a new link for an incoming connection. Provides the newly created Link that can be used for communication. @@ -276,7 +285,7 @@ public: /** Callbacks used when resolving names to IPs. */ class cResolveNameCallbacks { - public: + public: // Force a virtual destructor for all descendants: virtual ~cResolveNameCallbacks() {} @@ -310,11 +319,10 @@ public: /** Queues a TCP connection to be made to the specified host. - Calls one the connection callbacks (success, error) when the connection is successfully established, or upon failure. - The a_LinkCallbacks is passed to the newly created cTCPLink. - Returns true if queueing was successful, false on failure to queue. - Note that the return value doesn't report the success of the actual connection; the connection is established asynchronously in the background. - Implemented in TCPLinkImpl.cpp. */ + Calls one the connection callbacks (success, error) when the connection is successfully established, or upon + failure. The a_LinkCallbacks is passed to the newly created cTCPLink. Returns true if queueing was successful, false + on failure to queue. Note that the return value doesn't report the success of the actual connection; the connection + is established asynchronously in the background. Implemented in TCPLinkImpl.cpp. */ static bool Connect( const AString & a_Host, UInt16 a_Port, @@ -328,32 +336,23 @@ public: A cTCPLink with the specified link callbacks is created for each connection. Returns a cServerHandle that can be used to query the operation status and close the server. Implemented in ServerHandleImpl.cpp. */ - static cServerHandlePtr Listen( - UInt16 a_Port, - cListenCallbacksPtr a_ListenCallbacks - ); + static cServerHandlePtr Listen(UInt16 a_Port, cListenCallbacksPtr a_ListenCallbacks); /** Queues a DNS query to resolve the specified hostname to IP address. Calls one of the callbacks when the resolving succeeds, or when it fails. Returns true if queueing was successful, false if not. - Note that the return value doesn't report the success of the actual lookup; the lookup happens asynchronously on the background. - Implemented in HostnameLookup.cpp. */ - static bool HostnameToIP( - const AString & a_Hostname, - cResolveNameCallbacksPtr a_Callbacks - ); + Note that the return value doesn't report the success of the actual lookup; the lookup happens asynchronously on the + background. Implemented in HostnameLookup.cpp. */ + static bool HostnameToIP(const AString & a_Hostname, cResolveNameCallbacksPtr a_Callbacks); /** Queues a DNS query to resolve the specified IP address to a hostname. Calls one of the callbacks when the resolving succeeds, or when it fails. Returns true if queueing was successful, false if not. - Note that the return value doesn't report the success of the actual lookup; the lookup happens asynchronously on the background. - Implemented in IPLookup.cpp. */ - static bool IPToHostName( - const AString & a_IP, - cResolveNameCallbacksPtr a_Callbacks - ); + Note that the return value doesn't report the success of the actual lookup; the lookup happens asynchronously on the + background. Implemented in IPLookup.cpp. */ + static bool IPToHostName(const AString & a_IP, cResolveNameCallbacksPtr a_Callbacks); /** Opens up an UDP endpoint for sending and receiving UDP datagrams on the specified port. If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. @@ -363,6 +362,3 @@ public: /** Returns all local IP addresses for network interfaces currently available. */ static AStringVector EnumLocalIPAddresses(void); }; - - - diff --git a/src/OSSupport/NetworkInterfaceEnum.cpp b/src/OSSupport/NetworkInterfaceEnum.cpp index 439710c38..6cfc60b77 100644 --- a/src/OSSupport/NetworkInterfaceEnum.cpp +++ b/src/OSSupport/NetworkInterfaceEnum.cpp @@ -8,13 +8,13 @@ #include "event2/util.h" #if defined(_WIN32) - #include <IPHlpApi.h> - #pragma comment(lib, "IPHLPAPI.lib") +#include <IPHlpApi.h> +#pragma comment(lib, "IPHLPAPI.lib") #elif !defined(ANDROID) // _WIN32 - #include <sys/types.h> - #include <ifaddrs.h> - #include <netinet/in.h> - #include <arpa/inet.h> +#include <sys/types.h> +#include <ifaddrs.h> +#include <netinet/in.h> +#include <arpa/inet.h> #endif // else _WIN32 @@ -92,72 +92,70 @@ AStringVector cNetwork::EnumLocalIPAddresses(void) { AStringVector res; - #if defined(_WIN32) - - // Query the OS for all adapters' addresses: - char buffer[64 KiB]; // A buffer backing the address list - PIP_ADAPTER_ADDRESSES pAddresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer); - ULONG outBufLen = sizeof(buffer); - DWORD dwRetVal = GetAdaptersAddresses( - AF_UNSPEC, - GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, nullptr, - pAddresses, &outBufLen - ); - if (dwRetVal != ERROR_SUCCESS) +#if defined(_WIN32) + + // Query the OS for all adapters' addresses: + char buffer[64 KiB]; // A buffer backing the address list + PIP_ADAPTER_ADDRESSES pAddresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer); + ULONG outBufLen = sizeof(buffer); + DWORD dwRetVal = GetAdaptersAddresses( + AF_UNSPEC, + GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, + nullptr, + pAddresses, + &outBufLen + ); + if (dwRetVal != ERROR_SUCCESS) + { + LOG("GetAdaptersAddresses() failed: %u", dwRetVal); + return res; + } + + // Enumerate all active adapters + for (auto pCurrAddresses = pAddresses; pCurrAddresses != nullptr; pCurrAddresses = pCurrAddresses->Next) + { + if (pCurrAddresses->OperStatus != IfOperStatusUp) { - LOG("GetAdaptersAddresses() failed: %u", dwRetVal); - return res; + // Adapter not active, skip it: + continue; } - // Enumerate all active adapters - for (auto pCurrAddresses = pAddresses; pCurrAddresses != nullptr; pCurrAddresses = pCurrAddresses->Next) + // Collect all IP addresses on this adapter: + for (auto pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != nullptr; pUnicast = pUnicast->Next) { - if (pCurrAddresses->OperStatus != IfOperStatusUp) + auto Address = PrintAddress(pUnicast->Address); + if (!Address.empty()) { - // Adapter not active, skip it: - continue; + res.push_back(Address); } + } // for pUnicast + } // for pCurrAddresses - // Collect all IP addresses on this adapter: - for (auto pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != nullptr; pUnicast = pUnicast->Next) - { - auto Address = PrintAddress(pUnicast->Address); - if (!Address.empty()) - { - res.push_back(Address); - } - } // for pUnicast - } // for pCurrAddresses - - #elif !defined(ANDROID) // _WIN32 +#elif !defined(ANDROID) // _WIN32 - struct ifaddrs * ifAddrStruct = nullptr; - getifaddrs(&ifAddrStruct); + struct ifaddrs * ifAddrStruct = nullptr; + getifaddrs(&ifAddrStruct); - for (auto ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next) + for (auto ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == nullptr) { - if (ifa->ifa_addr == nullptr) - { - continue; - } - - auto Address = PrintAddress(ifa); - if (!Address.empty()) - { - res.emplace_back(Address); - } + continue; } - if (ifAddrStruct != nullptr) + auto Address = PrintAddress(ifa); + if (!Address.empty()) { - freeifaddrs(ifAddrStruct); + res.emplace_back(Address); } + } - #endif // else _WIN32 + if (ifAddrStruct != nullptr) + { + freeifaddrs(ifAddrStruct); + } + +#endif // else _WIN32 return res; } - - - - diff --git a/src/OSSupport/NetworkLookup.cpp b/src/OSSupport/NetworkLookup.cpp index 8a0e54015..458294c11 100644 --- a/src/OSSupport/NetworkLookup.cpp +++ b/src/OSSupport/NetworkLookup.cpp @@ -41,7 +41,7 @@ void cNetworkLookup::Stop() { m_ShouldTerminate = true; m_WorkQueue.Clear(); - m_WorkQueue.EnqueueItem([](){}); // Dummy work to wake up the thread + m_WorkQueue.EnqueueItem([]() {}); // Dummy work to wake up the thread cIsThread::Stop(); } @@ -58,6 +58,3 @@ void cNetworkLookup::Execute() Work(); } } - - - diff --git a/src/OSSupport/NetworkLookup.h b/src/OSSupport/NetworkLookup.h index 416219947..bb01de407 100644 --- a/src/OSSupport/NetworkLookup.h +++ b/src/OSSupport/NetworkLookup.h @@ -14,11 +14,9 @@ -class cNetworkLookup : - public cIsThread +class cNetworkLookup : public cIsThread { -public: - + public: cNetworkLookup(); virtual ~cNetworkLookup() override; @@ -28,15 +26,11 @@ public: /** Cancels any scheduled lookups and joins the lookup thread. */ void Stop(); -protected: - + protected: /** Process the queue until the thread is stopped. */ virtual void Execute() override final; -private: - + private: /** The queue of lookup tasks waiting to be executed. */ cQueue<std::function<void()>> m_WorkQueue; }; - - diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp index e022f4fec..e13f96515 100644 --- a/src/OSSupport/NetworkSingleton.cpp +++ b/src/OSSupport/NetworkSingleton.cpp @@ -49,30 +49,30 @@ void cNetworkSingleton::Initialise(void) // Start the lookup thread m_LookupThread.Start(); - // Windows: initialize networking: - #ifdef _WIN32 - WSADATA wsaData; - memset(&wsaData, 0, sizeof(wsaData)); - int res = WSAStartup (MAKEWORD(2, 2), &wsaData); - if (res != 0) - { - int err = WSAGetLastError(); - LOGWARNING("WSAStartup failed: %d, WSAGLE = %d (%s)", res, err, evutil_socket_error_to_string(err)); - exit(1); - } - #endif // _WIN32 +// Windows: initialize networking: +#ifdef _WIN32 + WSADATA wsaData; + memset(&wsaData, 0, sizeof(wsaData)); + int res = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (res != 0) + { + int err = WSAGetLastError(); + LOGWARNING("WSAStartup failed: %d, WSAGLE = %d (%s)", res, err, evutil_socket_error_to_string(err)); + exit(1); + } +#endif // _WIN32 // Initialize LibEvent logging: event_set_log_callback(LogCallback); - // Initialize threading: - #if defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED) - evthread_use_windows_threads(); - #elif defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) - evthread_use_pthreads(); - #else - #error No threading implemented for EVTHREAD - #endif +// Initialize threading: +#if defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED) + evthread_use_windows_threads(); +#elif defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) + evthread_use_pthreads(); +#else +#error No threading implemented for EVTHREAD +#endif // Create the main event_base: event_config * config = event_config_new(); @@ -88,7 +88,8 @@ void cNetworkSingleton::Initialise(void) // Create the event loop thread: m_HasTerminated = false; m_EventLoopThread = std::thread(RunEventLoop, this); - m_StartupEvent.Wait(); // Wait for the LibEvent loop to actually start running (otherwise calling Terminate too soon would hang, see #3228) + m_StartupEvent.Wait(); // Wait for the LibEvent loop to actually start running (otherwise calling Terminate too + // soon would hang, see #3228) } @@ -133,7 +134,8 @@ void cNetworkSingleton::Terminate(void) libevent_global_shutdown(); // Set the HasTerminated flag: - // (Only set the flag after everything has been removed, to avoid the random failures in the Google-test, caused by links terminating after this flag was set) + // (Only set the flag after everything has been removed, to avoid the random failures in the Google-test, caused by + // links terminating after this flag was set) m_HasTerminated = true; } @@ -145,10 +147,10 @@ void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) { switch (a_Severity) { - case _EVENT_LOG_DEBUG: LOGD ("LibEvent: %s", a_Msg); break; - case _EVENT_LOG_MSG: LOG ("LibEvent: %s", a_Msg); break; + case _EVENT_LOG_DEBUG: LOGD("LibEvent: %s", a_Msg); break; + case _EVENT_LOG_MSG: LOG("LibEvent: %s", a_Msg); break; case _EVENT_LOG_WARN: LOGWARNING("LibEvent: %s", a_Msg); break; - case _EVENT_LOG_ERR: LOGERROR ("LibEvent: %s", a_Msg); break; + case _EVENT_LOG_ERR: LOGERROR("LibEvent: %s", a_Msg); break; default: { LOGWARNING("LibEvent: Unknown log severity (%d): %s", a_Severity, a_Msg); @@ -164,7 +166,7 @@ void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self) { auto timer = evtimer_new(a_Self->m_EventBase, SignalizeStartup, a_Self); - timeval timeout{}; // Zero timeout - execute immediately + timeval timeout {}; // Zero timeout - execute immediately evtimer_add(timer, &timeout); event_base_loop(a_Self->m_EventBase, EVLOOP_NO_EXIT_ON_EMPTY); event_free(timer); @@ -238,7 +240,3 @@ void cNetworkSingleton::RemoveServer(const cServerHandle * a_Server) } } // for itr - m_Servers[] } - - - - diff --git a/src/OSSupport/NetworkSingleton.h b/src/OSSupport/NetworkSingleton.h index 2a2d0cef3..d2af6d3c8 100644 --- a/src/OSSupport/NetworkSingleton.h +++ b/src/OSSupport/NetworkSingleton.h @@ -37,7 +37,7 @@ typedef std::vector<cServerHandlePtr> cServerHandlePtrs; class cNetworkSingleton { -public: + public: cNetworkSingleton(); ~cNetworkSingleton() noexcept(false); @@ -50,7 +50,8 @@ public: /** Terminates all network-related threads. To be used only on app shutdown or restart. - MSVC runtime requires that the LibEvent networking be shut down before the main() function is exitted; this is the way to do it. */ + MSVC runtime requires that the LibEvent networking be shut down before the main() function is exitted; this is the + way to do it. */ void Terminate(void); /** Returns the main LibEvent handle for event registering. */ @@ -76,8 +77,7 @@ public: Used by the underlying server handle implementation when the server is closed. */ void RemoveServer(const cServerHandle * a_Server); -protected: - + protected: /** The main LibEvent container for driving the event loop. */ event_base * m_EventBase; @@ -112,12 +112,3 @@ protected: /** Callback called by LibEvent when the event loop is started. */ static void SignalizeStartup(evutil_socket_t a_Socket, short a_Events, void * a_Self); }; - - - - - - - - - diff --git a/src/OSSupport/Queue.h b/src/OSSupport/Queue.h index d5a4bd443..da0c88ec0 100644 --- a/src/OSSupport/Queue.h +++ b/src/OSSupport/Queue.h @@ -19,15 +19,14 @@ implements the functions Delete() and Combine(). An example is given in cQueueFuncs and is used as the default behavior. */ /** This empty struct allows for the callback functions to be inlined */ -template <class T> -struct cQueueFuncs +template <class T> struct cQueueFuncs { -public: - + public: /** Called when an Item is deleted from the queue without being returned */ static void Delete(T) {} - /** Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already inserted */ + /** Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already inserted + */ static void Combine(T & a_existing, const T & a_new) { UNUSED(a_existing); @@ -39,8 +38,7 @@ public: -template <class ItemType, class Funcs = cQueueFuncs<ItemType> > -class cQueue +template <class ItemType, class Funcs = cQueueFuncs<ItemType>> class cQueue { // The actual storage type for the queue typedef typename std::list<ItemType> QueueType; @@ -48,7 +46,7 @@ class cQueue // Make iterator an alias for the QueueType's iterator typedef typename QueueType::iterator iterator; -public: + public: cQueue() {} ~cQueue() {} @@ -62,7 +60,8 @@ public: } - /** Enqueues an item in the queue if not already present (as determined by operator ==). Blocks other threads from accessing the queue. */ + /** Enqueues an item in the queue if not already present (as determined by operator ==). Blocks other threads from + * accessing the queue. */ void EnqueueItemIfNotPresent(ItemType a_Item) { cCSLock Lock(m_CS); @@ -164,8 +163,7 @@ public: /** Removes all items for which the predicate returns true. */ - template <class Predicate> - void RemoveIf(Predicate a_Predicate) + template <class Predicate> void RemoveIf(Predicate a_Predicate) { cCSLock Lock(m_CS); for (auto itr = m_Contents.begin(); itr != m_Contents.end();) @@ -185,7 +183,7 @@ public: } // for itr - m_Contents[] } -private: + private: /** The contents of the queue */ QueueType m_Contents; @@ -198,7 +196,3 @@ private: /** Event that is signalled when an item is removed (both dequeued or erased) */ cEvent m_evtRemoved; }; - - - - diff --git a/src/OSSupport/ServerHandleImpl.cpp b/src/OSSupport/ServerHandleImpl.cpp index 669a0f83f..227f224aa 100644 --- a/src/OSSupport/ServerHandleImpl.cpp +++ b/src/OSSupport/ServerHandleImpl.cpp @@ -17,15 +17,15 @@ namespace ServerHandleImplHelper { - static bool IsValidSocket(evutil_socket_t a_Socket) - { +static bool IsValidSocket(evutil_socket_t a_Socket) +{ #ifdef _WIN32 - return (a_Socket != INVALID_SOCKET); + return (a_Socket != INVALID_SOCKET); #else // _WIN32 - return (a_Socket >= 0); + return (a_Socket >= 0); #endif // else _WIN32 - } } +} // namespace ServerHandleImplHelper @@ -34,7 +34,7 @@ namespace ServerHandleImplHelper //////////////////////////////////////////////////////////////////////////////// // cServerHandleImpl: -cServerHandleImpl::cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks): +cServerHandleImpl::cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks) : m_ListenCallbacks(std::move(a_ListenCallbacks)), m_ConnListener(nullptr), m_SecondaryConnListener(nullptr), @@ -82,7 +82,7 @@ void cServerHandleImpl::Close(void) cCSLock Lock(m_CS); std::swap(Conns, m_Connections); } - for (const auto & conn: Conns) + for (const auto & conn : Conns) { conn->Shutdown(); } @@ -98,12 +98,9 @@ void cServerHandleImpl::Close(void) -cServerHandleImplPtr cServerHandleImpl::Listen( - UInt16 a_Port, - cNetwork::cListenCallbacksPtr a_ListenCallbacks -) +cServerHandleImplPtr cServerHandleImpl::Listen(UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks) { - cServerHandleImplPtr res{new cServerHandleImpl(std::move(a_ListenCallbacks))}; + cServerHandleImplPtr res {new cServerHandleImpl(std::move(a_ListenCallbacks))}; res->m_SelfPtr = res; if (res->Listen(a_Port)) { @@ -141,8 +138,11 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (!ServerHandleImplHelper::IsValidSocket(MainSock)) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Cannot create a server socket for port {}: {} ({})"), - a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) + m_ErrorMsg = fmt::format( + FMT_STRING("Cannot create a server socket for port {}: {} ({})"), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) ); return false; } @@ -151,8 +151,11 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (evutil_make_listen_socket_reuseable(MainSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Port {} cannot be made reusable: {} ({}). Restarting the server might not work."), - a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) + m_ErrorMsg = fmt::format( + FMT_STRING("Port {} cannot be made reusable: {} ({}). Restarting the server might not work."), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) ); LOG("%s", m_ErrorMsg); } @@ -165,8 +168,11 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (bind(MainSock, reinterpret_cast<const sockaddr *>(&name), sizeof(name)) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Cannot bind IPv4 socket to port {}: {} ({})"), - a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) + m_ErrorMsg = fmt::format( + FMT_STRING("Cannot bind IPv4 socket to port {}: {} ({})"), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) ); evutil_closesocket(MainSock); return false; @@ -176,21 +182,24 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) { // IPv6 socket created, switch it into "dualstack" mode: UInt32 Zero = 0; - #ifdef _WIN32 - // WinXP doesn't support this feature, so if the setting fails, create another socket later on: - int res = setsockopt(MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); - err = EVUTIL_SOCKET_ERROR(); - NeedsTwoSockets = ((res == SOCKET_ERROR) && (err == WSAENOPROTOOPT)); - #else - setsockopt(MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); - #endif +#ifdef _WIN32 + // WinXP doesn't support this feature, so if the setting fails, create another socket later on: + int res = setsockopt(MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); + err = EVUTIL_SOCKET_ERROR(); + NeedsTwoSockets = ((res == SOCKET_ERROR) && (err == WSAENOPROTOOPT)); +#else + setsockopt(MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); +#endif // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(MainSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Port {} cannot be made reusable: {} ({}). Restarting the server might not work."), - a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) + m_ErrorMsg = fmt::format( + FMT_STRING("Port {} cannot be made reusable: {} ({}). Restarting the server might not work."), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) ); LOG("%s", m_ErrorMsg); } @@ -203,7 +212,12 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (bind(MainSock, reinterpret_cast<const sockaddr *>(&name), sizeof(name)) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Cannot bind IPv6 socket to port {}: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode)); + m_ErrorMsg = fmt::format( + FMT_STRING("Cannot bind IPv6 socket to port {}: {} ({})"), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) + ); evutil_closesocket(MainSock); return false; } @@ -211,18 +225,35 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (evutil_make_socket_nonblocking(MainSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Cannot make socket on port {} non-blocking: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode)); + m_ErrorMsg = fmt::format( + FMT_STRING("Cannot make socket on port {} non-blocking: {} ({})"), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) + ); evutil_closesocket(MainSock); return false; } if (listen(MainSock, SOMAXCONN) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Cannot listen on port {}: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode)); + m_ErrorMsg = fmt::format( + FMT_STRING("Cannot listen on port {}: {} ({})"), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) + ); evutil_closesocket(MainSock); return false; } - m_ConnListener = evconnlistener_new(cNetworkSingleton::Get().GetEventBase(), Callback, this, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 0, MainSock); + m_ConnListener = evconnlistener_new( + cNetworkSingleton::Get().GetEventBase(), + Callback, + this, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, + 0, + MainSock + ); m_IsListening = true; if (!NeedsTwoSockets) @@ -245,8 +276,12 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (evutil_make_listen_socket_reuseable(SecondSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); - m_ErrorMsg = fmt::format(FMT_STRING("Port {} cannot be made reusable (second socket): {} ({}). Restarting the server might not work."), - a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) + m_ErrorMsg = fmt::format( + FMT_STRING("Port {} cannot be made reusable (second socket): {} ({}). Restarting the server might not work." + ), + a_Port, + m_ErrorCode, + evutil_socket_error_to_string(m_ErrorCode) ); LOG("%s", m_ErrorMsg); } @@ -255,7 +290,11 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) if (evutil_make_socket_nonblocking(SecondSock) != 0) { err = EVUTIL_SOCKET_ERROR(); - LOGD("evutil_make_socket_nonblocking() failed for secondary socket: %d, %s", err, evutil_socket_error_to_string(err)); + LOGD( + "evutil_make_socket_nonblocking() failed for secondary socket: %d, %s", + err, + evutil_socket_error_to_string(err) + ); evutil_closesocket(SecondSock); return true; // Report as success, the primary socket is working } @@ -283,7 +322,14 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) UNUSED(err); - m_SecondaryConnListener = evconnlistener_new(cNetworkSingleton::Get().GetEventBase(), Callback, this, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 0, SecondSock); + m_SecondaryConnListener = evconnlistener_new( + cNetworkSingleton::Get().GetEventBase(), + Callback, + this, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, + 0, + SecondSock + ); return true; } @@ -291,7 +337,13 @@ bool cServerHandleImpl::Listen(UInt16 a_Port) -void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self) +void cServerHandleImpl::Callback( + evconnlistener * a_Listener, + evutil_socket_t a_Socket, + sockaddr * a_Addr, + int a_Len, + void * a_Self +) { // Cast to true self: cServerHandleImpl * Self = static_cast<cServerHandleImpl *>(a_Self); @@ -332,7 +384,8 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_ setsockopt(a_Socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&one), sizeof(one)); // Create a new cTCPLink for the incoming connection: - cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, LinkCallbacks, Self->m_SelfPtr, a_Addr, static_cast<socklen_t>(a_Len)); + cTCPLinkImplPtr Link = + std::make_shared<cTCPLinkImpl>(a_Socket, LinkCallbacks, Self->m_SelfPtr, a_Addr, static_cast<socklen_t>(a_Len)); { cCSLock Lock(Self->m_CS); Self->m_Connections.push_back(Link); @@ -368,15 +421,7 @@ void cServerHandleImpl::RemoveLink(const cTCPLinkImpl * a_Link) //////////////////////////////////////////////////////////////////////////////// // cNetwork API: -cServerHandlePtr cNetwork::Listen( - UInt16 a_Port, - cNetwork::cListenCallbacksPtr a_ListenCallbacks -) +cServerHandlePtr cNetwork::Listen(UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks) { return cServerHandleImpl::Listen(a_Port, std::move(a_ListenCallbacks)); } - - - - - diff --git a/src/OSSupport/ServerHandleImpl.h b/src/OSSupport/ServerHandleImpl.h index eb0dca386..af06d971f 100644 --- a/src/OSSupport/ServerHandleImpl.h +++ b/src/OSSupport/ServerHandleImpl.h @@ -31,37 +31,34 @@ typedef std::vector<cServerHandleImplPtr> cServerHandleImplPtrs; -class cServerHandleImpl: - public cServerHandle +class cServerHandleImpl : public cServerHandle { using Super = cServerHandle; friend class cTCPLinkImpl; -public: - + public: /** Closes the server, dropping all the connections. */ virtual ~cServerHandleImpl() override; /** Creates a new server instance listening on the specified port. Both IPv4 and IPv6 interfaces are used, if possible. - Always returns a server instance; in the event of a failure, the instance holds the error details. Use IsListening() to query success. */ - static cServerHandleImplPtr Listen( - UInt16 a_Port, - cNetwork::cListenCallbacksPtr a_ListenCallbacks - ); + Always returns a server instance; in the event of a failure, the instance holds the error details. Use IsListening() + to query success. */ + static cServerHandleImplPtr Listen(UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks); // cServerHandle overrides: virtual void Close(void) override; virtual bool IsListening(void) const override { return m_IsListening; } -protected: + protected: /** The callbacks used to notify about incoming connections. */ cNetwork::cListenCallbacksPtr m_ListenCallbacks; /** The LibEvent handle representing the main listening socket. */ evconnlistener * m_ConnListener; - /** The LibEvent handle representing the secondary listening socket (only when side-by-side listening is needed, such as WinXP). */ + /** The LibEvent handle representing the secondary listening socket (only when side-by-side listening is needed, + * such as WinXP). */ evconnlistener * m_SecondaryConnListener; /** Set to true when the server is initialized successfully and is listening for incoming connections. */ @@ -93,14 +90,15 @@ protected: bool Listen(UInt16 a_Port); /** The callback called by LibEvent upon incoming connection. */ - static void Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self); + static void Callback( + evconnlistener * a_Listener, + evutil_socket_t a_Socket, + sockaddr * a_Addr, + int a_Len, + void * a_Self + ); /** Removes the specified link from m_Connections. Called by cTCPLinkImpl when the link is terminated. */ void RemoveLink(const cTCPLinkImpl * a_Link); }; - - - - - diff --git a/src/OSSupport/SleepResolutionBooster.h b/src/OSSupport/SleepResolutionBooster.h index f090f6963..956a009ef 100644 --- a/src/OSSupport/SleepResolutionBooster.h +++ b/src/OSSupport/SleepResolutionBooster.h @@ -25,42 +25,36 @@ static TIMECAPS g_Resolution; namespace SleepResolutionBooster { - static void Register() +static void Register() +{ + // Default sleep resolution on Windows isn't accurate enough (GH #5140) so try to boost it: + if ((timeGetDevCaps(&g_Resolution, sizeof(g_Resolution)) == MMSYSERR_NOERROR) && + (timeBeginPeriod(g_Resolution.wPeriodMin) == MMSYSERR_NOERROR)) { - // Default sleep resolution on Windows isn't accurate enough (GH #5140) so try to boost it: - if ( - (timeGetDevCaps(&g_Resolution, sizeof(g_Resolution)) == MMSYSERR_NOERROR) && - (timeBeginPeriod(g_Resolution.wPeriodMin) == MMSYSERR_NOERROR) - ) - { - return; - } - - // Max < Min sentinel for failure, to prevent bogus timeEndPeriod calls: - g_Resolution.wPeriodMax = 0; - g_Resolution.wPeriodMin = 1; + return; } - static void Unregister() + // Max < Min sentinel for failure, to prevent bogus timeEndPeriod calls: + g_Resolution.wPeriodMax = 0; + g_Resolution.wPeriodMin = 1; +} + +static void Unregister() +{ + if (g_Resolution.wPeriodMax >= g_Resolution.wPeriodMin) { - if (g_Resolution.wPeriodMax >= g_Resolution.wPeriodMin) - { - timeEndPeriod(g_Resolution.wPeriodMin); - } + timeEndPeriod(g_Resolution.wPeriodMin); } -}; +} +}; // namespace SleepResolutionBooster #else namespace SleepResolutionBooster { - static void Register() - { - } +static void Register() {} - static void Unregister() - { - } -}; +static void Unregister() {} +}; // namespace SleepResolutionBooster #endif diff --git a/src/OSSupport/StackTrace.cpp b/src/OSSupport/StackTrace.cpp index 77c5a3724..5466d0617 100644 --- a/src/OSSupport/StackTrace.cpp +++ b/src/OSSupport/StackTrace.cpp @@ -6,12 +6,12 @@ #include "Globals.h" #include "StackTrace.h" #ifdef _WIN32 - #include "WinStackWalker.h" +#include "WinStackWalker.h" #else - #ifdef __GLIBC__ - #include <execinfo.h> - #endif - #include <unistd.h> +#ifdef __GLIBC__ +#include <execinfo.h> +#endif +#include <unistd.h> #endif @@ -20,23 +20,20 @@ void PrintStackTrace(void) { - #ifdef _WIN32 - class PrintingStackWalker: - public WinStackWalker - { - virtual void OnOutput(LPCSTR szText) override - { - std::fputs(szText, stdout); - } - } sw; - sw.ShowCallstack(); - #else - #ifdef __GLIBC__ - // Use the backtrace() function to get and output the stackTrace: - // Code adapted from https://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes - void * stackTrace[30]; - auto numItems = backtrace(stackTrace, ARRAYCOUNT(stackTrace)); - backtrace_symbols_fd(stackTrace, numItems, STDERR_FILENO); - #endif - #endif +#ifdef _WIN32 + class PrintingStackWalker : public WinStackWalker + { + virtual void OnOutput(LPCSTR szText) override { std::fputs(szText, stdout); } + } sw; + sw.ShowCallstack(); +#else +#ifdef __GLIBC__ + // Use the backtrace() function to get and output the stackTrace: + // Code adapted from + // https://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes + void * stackTrace[30]; + auto numItems = backtrace(stackTrace, ARRAYCOUNT(stackTrace)); + backtrace_symbols_fd(stackTrace, numItems, STDERR_FILENO); +#endif +#endif } diff --git a/src/OSSupport/StackTrace.h b/src/OSSupport/StackTrace.h index 228a00077..cff1bb8af 100644 --- a/src/OSSupport/StackTrace.h +++ b/src/OSSupport/StackTrace.h @@ -9,7 +9,3 @@ /** Prints the stacktrace for the current thread. */ extern void PrintStackTrace(void); - - - - diff --git a/src/OSSupport/StartAsService.h b/src/OSSupport/StartAsService.h index fe078f303..a7811494b 100644 --- a/src/OSSupport/StartAsService.h +++ b/src/OSSupport/StartAsService.h @@ -13,16 +13,13 @@ class StartAsService { -public: - + public: /** Make a Windows service. */ - template <auto UniversalMain> - static bool MakeIntoService() + template <auto UniversalMain> static bool MakeIntoService() { - SERVICE_TABLE_ENTRY ServiceTable[] = - { - { g_ServiceName, (LPSERVICE_MAIN_FUNCTION)serviceMain<UniversalMain> }, - { nullptr, nullptr } + SERVICE_TABLE_ENTRY ServiceTable[] = { + {g_ServiceName, (LPSERVICE_MAIN_FUNCTION) serviceMain<UniversalMain>}, + {nullptr, nullptr} }; if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) @@ -33,8 +30,7 @@ public: return true; } -private: - + private: /** Set the internal status of the service */ static void serviceSetState(DWORD acceptedControls, DWORD newState, DWORD exitCode) { @@ -64,8 +60,7 @@ private: } /* Startup logic for running as a service */ - template <auto MainFunction> - static void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) + template <auto MainFunction> static void WINAPI serviceMain(DWORD argc, TCHAR * argv[]) { wchar_t applicationFilename[MAX_PATH]; wchar_t applicationDirectory[MAX_PATH]; @@ -110,7 +105,7 @@ private: serviceSetState(SERVICE_ACCEPT_STOP, SERVICE_RUNNING, 0); char MultibyteArgV0[MAX_PATH]; - char * MultibyteArgV[] = { MultibyteArgV0 }; + char * MultibyteArgV[] = {MultibyteArgV0}; const auto OutputSize = std::size(MultibyteArgV0); const auto TranslateResult = std::wcstombs(MultibyteArgV0, argv[0], OutputSize); @@ -132,9 +127,9 @@ private: serviceSetState(0, SERVICE_STOPPED, Return); } - static inline SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; - static inline HANDLE g_ServiceThread = INVALID_HANDLE_VALUE; - static inline wchar_t g_ServiceName[] = L"Cuberite"; + static inline SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; + static inline HANDLE g_ServiceThread = INVALID_HANDLE_VALUE; + static inline wchar_t g_ServiceName[] = L"Cuberite"; }; #else @@ -142,8 +137,7 @@ private: struct StartAsService { /** Make a UNIX daemon. */ - template <auto> - static bool MakeIntoService() + template <auto> static bool MakeIntoService() { pid_t pid = fork(); @@ -159,7 +153,7 @@ struct StartAsService return true; } - // Child process now goes quiet, running in the background. + // Child process now goes quiet, running in the background. close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); diff --git a/src/OSSupport/Stopwatch.h b/src/OSSupport/Stopwatch.h index 7676b3856..647f4773a 100644 --- a/src/OSSupport/Stopwatch.h +++ b/src/OSSupport/Stopwatch.h @@ -15,24 +15,22 @@ class cStopwatch { -public: - cStopwatch(const AString & a_Name): - m_Name(a_Name), - m_StartTime(std::chrono::high_resolution_clock::now()) + public: + cStopwatch(const AString & a_Name) : + m_Name(a_Name), m_StartTime(std::chrono::high_resolution_clock::now()) { } ~cStopwatch() { - auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_StartTime).count(); + auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::high_resolution_clock::now() - m_StartTime + ) + .count(); LOG("Stopwatch: %s took %.03f sec", m_Name, static_cast<double>(duration) / 1000); } -protected: + protected: AString m_Name; std::chrono::high_resolution_clock::time_point m_StartTime; }; - - - - diff --git a/src/OSSupport/TCPLinkImpl.cpp b/src/OSSupport/TCPLinkImpl.cpp index 1e12f27ab..d1cc2e8d2 100644 --- a/src/OSSupport/TCPLinkImpl.cpp +++ b/src/OSSupport/TCPLinkImpl.cpp @@ -17,9 +17,13 @@ //////////////////////////////////////////////////////////////////////////////// // cTCPLinkImpl: -cTCPLinkImpl::cTCPLinkImpl(const std::string & a_Host, cTCPLink::cCallbacksPtr a_LinkCallbacks): +cTCPLinkImpl::cTCPLinkImpl(const std::string & a_Host, cTCPLink::cCallbacksPtr a_LinkCallbacks) : Super(std::move(a_LinkCallbacks)), - m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().GetEventBase(), -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS)), + m_BufferEvent(bufferevent_socket_new( + cNetworkSingleton::Get().GetEventBase(), + -1, + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS + )), m_LocalPort(0), m_RemoteHost(a_Host), m_RemotePort(0), @@ -37,9 +41,13 @@ cTCPLinkImpl::cTCPLinkImpl( cServerHandleImplPtr a_Server, const sockaddr * a_Address, socklen_t a_AddrLen -): +) : Super(std::move(a_LinkCallbacks)), - m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().GetEventBase(), a_Socket, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS)), + m_BufferEvent(bufferevent_socket_new( + cNetworkSingleton::Get().GetEventBase(), + a_Socket, + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS + )), m_Server(std::move(a_Server)), m_LocalPort(0), m_RemotePort(0), @@ -66,32 +74,34 @@ cTCPLinkImpl::~cTCPLinkImpl() -cTCPLinkImplPtr cTCPLinkImpl::Connect(const AString & a_Host, UInt16 a_Port, cTCPLink::cCallbacksPtr a_LinkCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks) +cTCPLinkImplPtr cTCPLinkImpl::Connect( + const AString & a_Host, + UInt16 a_Port, + cTCPLink::cCallbacksPtr a_LinkCallbacks, + cNetwork::cConnectCallbacksPtr a_ConnectCallbacks +) { ASSERT(a_LinkCallbacks != nullptr); ASSERT(a_ConnectCallbacks != nullptr); // Create a new link: - cTCPLinkImplPtr res{new cTCPLinkImpl(a_Host, std::move(a_LinkCallbacks))}; // Cannot use std::make_shared here, constructor is not accessible + cTCPLinkImplPtr res {new cTCPLinkImpl(a_Host, std::move(a_LinkCallbacks)) + }; // Cannot use std::make_shared here, constructor is not accessible res->m_ConnectCallbacks = std::move(a_ConnectCallbacks); cNetworkSingleton::Get().AddLink(res); res->m_Callbacks->OnLinkCreated(res); res->Enable(res); // Callback to connect after performing lookup: - class cHostnameCallback : - public cNetwork::cResolveNameCallbacks + class cHostnameCallback : public cNetwork::cResolveNameCallbacks { cTCPLinkImplPtr m_Link; UInt16 m_Port; bool m_IsConnecting; - public: - - cHostnameCallback(cTCPLinkImplPtr a_Link, UInt16 a_ConnectPort): - m_Link(std::move(a_Link)), - m_Port(a_ConnectPort), - m_IsConnecting(false) + public: + cHostnameCallback(cTCPLinkImplPtr a_Link, UInt16 a_ConnectPort) : + m_Link(std::move(a_Link)), m_Port(a_ConnectPort), m_IsConnecting(false) { } @@ -135,13 +145,9 @@ cTCPLinkImplPtr cTCPLinkImpl::Connect(const AString & a_Host, UInt16 a_Port, cTC } // Don't need to do anything for these - virtual void OnFinished() override - { - } + virtual void OnFinished() override {} - virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override - { - } + virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override {} }; // Schedule the host query @@ -242,11 +248,7 @@ void cTCPLinkImpl::Close(void) -AString cTCPLinkImpl::StartTLSClient( - cX509CertPtr a_OwnCert, - cCryptoKeyPtr a_OwnPrivKey, - cX509CertPtr a_TrustedRootCAs -) +AString cTCPLinkImpl::StartTLSClient(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, cX509CertPtr a_TrustedRootCAs) { // Check preconditions: if (m_TlsContext != nullptr) @@ -298,11 +300,7 @@ AString cTCPLinkImpl::StartTLSClient( -AString cTCPLinkImpl::StartTLSServer( - cX509CertPtr a_OwnCert, - cCryptoKeyPtr a_OwnPrivKey, - const AString & a_StartTLSData -) +AString cTCPLinkImpl::StartTLSServer(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, const AString & a_StartTLSData) { // Check preconditions: if (m_TlsContext != nullptr) @@ -529,11 +527,11 @@ void cTCPLinkImpl::UpdateRemoteAddress(void) void cTCPLinkImpl::DoActualShutdown(void) { - #ifdef _WIN32 - shutdown(bufferevent_getfd(m_BufferEvent), SD_SEND); - #else - shutdown(bufferevent_getfd(m_BufferEvent), SHUT_WR); - #endif +#ifdef _WIN32 + shutdown(bufferevent_getfd(m_BufferEvent), SD_SEND); +#else + shutdown(bufferevent_getfd(m_BufferEvent), SHUT_WR); +#endif bufferevent_disable(m_BufferEvent, EV_WRITE); } @@ -563,7 +561,7 @@ void cTCPLinkImpl::ReceivedCleartextData(const char * a_Data, size_t a_Length) //////////////////////////////////////////////////////////////////////////////// // cTCPLinkImpl::cLinkTlsContext: -cTCPLinkImpl::cLinkTlsContext::cLinkTlsContext(cTCPLinkImpl & a_Link): +cTCPLinkImpl::cLinkTlsContext::cLinkTlsContext(cTCPLinkImpl & a_Link) : m_Link(a_Link) { } @@ -724,11 +722,7 @@ bool cNetwork::Connect( ) { // Add a connection request to the queue: - cTCPLinkImplPtr Conn = cTCPLinkImpl::Connect(a_Host, a_Port, std::move(a_LinkCallbacks), std::move(a_ConnectCallbacks)); + cTCPLinkImplPtr Conn = + cTCPLinkImpl::Connect(a_Host, a_Port, std::move(a_LinkCallbacks), std::move(a_ConnectCallbacks)); return (Conn != nullptr); } - - - - - diff --git a/src/OSSupport/TCPLinkImpl.h b/src/OSSupport/TCPLinkImpl.h index 44e515504..1ce4b0232 100644 --- a/src/OSSupport/TCPLinkImpl.h +++ b/src/OSSupport/TCPLinkImpl.h @@ -31,13 +31,11 @@ typedef std::vector<cTCPLinkImplPtr> cTCPLinkImplPtrs; -class cTCPLinkImpl: - public cTCPLink +class cTCPLinkImpl : public cTCPLink { using Super = cTCPLink; -public: - + public: /** Creates a new link based on the given socket. Used for connections accepted in a server using cNetwork::Listen(). a_Host is the hostname used for TLS SNI (can be empty in cases TLS is not used). @@ -57,7 +55,12 @@ public: /** Queues a connection request to the specified host. a_ConnectCallbacks must be valid. Returns a link that has the connection request queued, or NULL for failure. */ - static cTCPLinkImplPtr Connect(const AString & a_Host, UInt16 a_Port, cTCPLink::cCallbacksPtr a_LinkCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks); + static cTCPLinkImplPtr Connect( + const AString & a_Host, + UInt16 a_Port, + cTCPLink::cCallbacksPtr a_LinkCallbacks, + cNetwork::cConnectCallbacksPtr a_ConnectCallbacks + ); /** Enables communication over the link. Links are created with communication disabled, so that creation callbacks can be called first. @@ -73,27 +76,19 @@ public: virtual UInt16 GetRemotePort(void) const override { return m_RemotePort; } virtual void Shutdown(void) override; virtual void Close(void) override; - virtual AString StartTLSClient( - cX509CertPtr a_OwnCert, - cCryptoKeyPtr a_OwnPrivKey, - cX509CertPtr a_TrustedRootCAs - ) override; - virtual AString StartTLSServer( - cX509CertPtr a_OwnCert, - cCryptoKeyPtr a_OwnPrivKey, - const AString & a_StartTLSData - ) override; - -protected: + virtual AString StartTLSClient(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, cX509CertPtr a_TrustedRootCAs) + override; + virtual AString StartTLSServer(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, const AString & a_StartTLSData) + override; + protected: // fwd: class cLinkTlsContext; typedef std::shared_ptr<cLinkTlsContext> cLinkTlsContextPtr; typedef std::weak_ptr<cLinkTlsContext> cLinkTlsContextWPtr; /** Wrapper around cSslContext that is used when this link is being encrypted by SSL. */ - class cLinkTlsContext : - public cSslContext + class cLinkTlsContext : public cSslContext { cTCPLinkImpl & m_Link; @@ -106,7 +101,7 @@ protected: /** Shared ownership of self, so that this object can keep itself alive for as long as it needs. */ cLinkTlsContextWPtr m_Self; - public: + public: cLinkTlsContext(cTCPLinkImpl & a_Link); /** Shares ownership of self, so that this object can keep itself alive for as long as it needs. */ @@ -134,10 +129,7 @@ protected: virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override; /** Returns true if the context's associated TCP link is the same link as a_Link. */ - bool IsLink(cTCPLinkImpl * a_Link) - { - return (a_Link == &m_Link); - } + bool IsLink(cTCPLinkImpl * a_Link) { return (a_Link == &m_Link); } }; @@ -216,7 +208,3 @@ protected: /** Called by the TLS when it has decoded a piece of incoming cleartext data from the socket. */ void ReceivedCleartextData(const char * a_Data, size_t a_Length); }; - - - - diff --git a/src/OSSupport/UDPEndpointImpl.cpp b/src/OSSupport/UDPEndpointImpl.cpp index 2550c5378..3ae5db485 100644 --- a/src/OSSupport/UDPEndpointImpl.cpp +++ b/src/OSSupport/UDPEndpointImpl.cpp @@ -16,15 +16,15 @@ namespace UDPEndpointImplHelper { - static bool IsValidSocket(evutil_socket_t a_Socket) - { +static bool IsValidSocket(evutil_socket_t a_Socket) +{ #ifdef _WIN32 - return (a_Socket != INVALID_SOCKET); + return (a_Socket != INVALID_SOCKET); #else // _WIN32 - return (a_Socket >= 0); + return (a_Socket >= 0); #endif // else _WIN32 - } } +} // namespace UDPEndpointImplHelper @@ -37,8 +37,8 @@ static void ConvertIPv4ToMappedIPv6(sockaddr_in & a_SrcAddr, sockaddr_in6 & a_Ds a_DstAddr.sin6_family = AF_INET6; a_DstAddr.sin6_addr.s6_addr[10] = 0xff; a_DstAddr.sin6_addr.s6_addr[11] = 0xff; - a_DstAddr.sin6_addr.s6_addr[12] = static_cast<Byte>((a_SrcAddr.sin_addr.s_addr >> 0) & 0xff); - a_DstAddr.sin6_addr.s6_addr[13] = static_cast<Byte>((a_SrcAddr.sin_addr.s_addr >> 8) & 0xff); + a_DstAddr.sin6_addr.s6_addr[12] = static_cast<Byte>((a_SrcAddr.sin_addr.s_addr >> 0) & 0xff); + a_DstAddr.sin6_addr.s6_addr[13] = static_cast<Byte>((a_SrcAddr.sin_addr.s_addr >> 8) & 0xff); a_DstAddr.sin6_addr.s6_addr[14] = static_cast<Byte>((a_SrcAddr.sin_addr.s_addr >> 16) & 0xff); a_DstAddr.sin6_addr.s6_addr[15] = static_cast<Byte>((a_SrcAddr.sin_addr.s_addr >> 24) & 0xff); a_DstAddr.sin6_port = a_SrcAddr.sin_port; @@ -54,11 +54,16 @@ static void ConvertIPv4ToMappedIPv6(sockaddr_in & a_SrcAddr, sockaddr_in6 & a_Ds /** A hostname-to-IP resolver callback that sends the data stored within to the resolved IP address. This is used for sending UDP datagrams to hostnames, so that the cUDPEndpoint::Send() doesn't block. Instead an instance of this callback is queued for resolving and the data is sent once the IP is resolved. */ -class cUDPSendAfterLookup: - public cNetwork::cResolveNameCallbacks +class cUDPSendAfterLookup : public cNetwork::cResolveNameCallbacks { -public: - cUDPSendAfterLookup(const AString & a_Data, UInt16 a_Port, evutil_socket_t a_MainSock, evutil_socket_t a_SecondSock, bool a_IsMainSockIPv6): + public: + cUDPSendAfterLookup( + const AString & a_Data, + UInt16 a_Port, + evutil_socket_t a_MainSock, + evutil_socket_t a_SecondSock, + bool a_IsMainSockIPv6 + ) : m_Data(a_Data), m_Port(a_Port), m_MainSock(a_MainSock), @@ -69,7 +74,7 @@ public: { } -protected: + protected: /** The data to send after the hostname is resolved. */ AString m_Data; @@ -137,20 +142,41 @@ protected: { if (m_HasIPv6) { - sendto(m_MainSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast<const sockaddr *>(&m_AddrIPv6), static_cast<socklen_t>(sizeof(m_AddrIPv6))); + sendto( + m_MainSock, + m_Data.data(), + m_Data.size(), + 0, + reinterpret_cast<const sockaddr *>(&m_AddrIPv6), + static_cast<socklen_t>(sizeof(m_AddrIPv6)) + ); } else if (m_HasIPv4) { // If the secondary socket is valid, it is an IPv4 socket, so use that: if (m_SecondSock != -1) { - sendto(m_SecondSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast<const sockaddr *>(&m_AddrIPv4), static_cast<socklen_t>(sizeof(m_AddrIPv4))); + sendto( + m_SecondSock, + m_Data.data(), + m_Data.size(), + 0, + reinterpret_cast<const sockaddr *>(&m_AddrIPv4), + static_cast<socklen_t>(sizeof(m_AddrIPv4)) + ); } else { // Need an address conversion from IPv4 to IPv6-mapped-IPv4: ConvertIPv4ToMappedIPv6(m_AddrIPv4, m_AddrIPv6); - sendto(m_MainSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast<const sockaddr *>(&m_AddrIPv6), static_cast<socklen_t>(sizeof(m_AddrIPv6))); + sendto( + m_MainSock, + m_Data.data(), + m_Data.size(), + 0, + reinterpret_cast<const sockaddr *>(&m_AddrIPv6), + static_cast<socklen_t>(sizeof(m_AddrIPv6)) + ); } } else @@ -167,7 +193,14 @@ protected: LOGD("UDP endpoint queued sendto: Name not resolved to IPv4 for an IPv4-only socket"); return; } - sendto(m_MainSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast<const sockaddr *>(&m_AddrIPv4), static_cast<socklen_t>(sizeof(m_AddrIPv4))); + sendto( + m_MainSock, + m_Data.data(), + m_Data.size(), + 0, + reinterpret_cast<const sockaddr *>(&m_AddrIPv4), + static_cast<socklen_t>(sizeof(m_AddrIPv4)) + ); } } @@ -184,7 +217,7 @@ protected: //////////////////////////////////////////////////////////////////////////////// // cUDPEndpointImpl: -cUDPEndpointImpl::cUDPEndpointImpl(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks): +cUDPEndpointImpl::cUDPEndpointImpl(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks) : Super(a_Callbacks), m_Port(0), m_MainSock(-1), @@ -270,7 +303,8 @@ bool cUDPEndpointImpl::Send(const AString & a_Payload, const AString & a_Host, U if (evutil_parse_sockaddr_port(a_Host.c_str(), reinterpret_cast<sockaddr *>(&sa), &salen) != 0) { // a_Host is a hostname, we need to do a lookup first: - auto queue = std::make_shared<cUDPSendAfterLookup>(a_Payload, a_Port, m_MainSock, m_SecondarySock, m_IsMainSockIPv6); + auto queue = + std::make_shared<cUDPSendAfterLookup>(a_Payload, a_Port, m_MainSock, m_SecondarySock, m_IsMainSockIPv6); return cNetwork::HostnameToIP(a_Host, queue); } @@ -287,19 +321,40 @@ bool cUDPEndpointImpl::Send(const AString & a_Payload, const AString & a_Host, U if (UDPEndpointImplHelper::IsValidSocket(m_SecondarySock)) { // The secondary socket, which is always IPv4, is present: - NumSent = static_cast<int>(sendto(m_SecondarySock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast<const sockaddr *>(&sa), static_cast<socklen_t>(salen))); + NumSent = static_cast<int>(sendto( + m_SecondarySock, + a_Payload.data(), + a_Payload.size(), + 0, + reinterpret_cast<const sockaddr *>(&sa), + static_cast<socklen_t>(salen) + )); } else { // Need to convert IPv4 to IPv6 address before sending: sockaddr_in6 IPv6; ConvertIPv4ToMappedIPv6(*reinterpret_cast<sockaddr_in *>(&sa), IPv6); - NumSent = static_cast<int>(sendto(m_MainSock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast<const sockaddr *>(&IPv6), static_cast<socklen_t>(sizeof(IPv6)))); + NumSent = static_cast<int>(sendto( + m_MainSock, + a_Payload.data(), + a_Payload.size(), + 0, + reinterpret_cast<const sockaddr *>(&IPv6), + static_cast<socklen_t>(sizeof(IPv6)) + )); } } else { - NumSent = static_cast<int>(sendto(m_MainSock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast<const sockaddr *>(&sa), static_cast<socklen_t>(salen))); + NumSent = static_cast<int>(sendto( + m_MainSock, + a_Payload.data(), + a_Payload.size(), + 0, + reinterpret_cast<const sockaddr *>(&sa), + static_cast<socklen_t>(salen) + )); } break; } @@ -307,7 +362,14 @@ bool cUDPEndpointImpl::Send(const AString & a_Payload, const AString & a_Host, U case AF_INET6: { reinterpret_cast<sockaddr_in6 *>(&sa)->sin6_port = htons(a_Port); - NumSent = static_cast<int>(sendto(m_MainSock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast<const sockaddr *>(&sa), static_cast<socklen_t>(salen))); + NumSent = static_cast<int>(sendto( + m_MainSock, + a_Payload.data(), + a_Payload.size(), + 0, + reinterpret_cast<const sockaddr *>(&sa), + static_cast<socklen_t>(salen) + )); break; } default: @@ -332,7 +394,13 @@ void cUDPEndpointImpl::EnableBroadcasts(void) int broadcastInt = 1; char broadcastChar = 1; // (Note that Windows uses const char * for option values, while Linux uses const void *) - if (setsockopt(m_MainSock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char *>(&broadcastInt), sizeof(broadcastInt)) == -1) + if (setsockopt( + m_MainSock, + SOL_SOCKET, + SO_BROADCAST, + reinterpret_cast<const char *>(&broadcastInt), + sizeof(broadcastInt) + ) == -1) { if (setsockopt(m_MainSock, SOL_SOCKET, SO_BROADCAST, &broadcastChar, sizeof(broadcastChar)) == -1) { @@ -347,7 +415,12 @@ void cUDPEndpointImpl::EnableBroadcasts(void) if (setsockopt(m_SecondarySock, SOL_SOCKET, SO_BROADCAST, &broadcastChar, sizeof(broadcastChar)) == -1) { int err = EVUTIL_SOCKET_ERROR(); - LOGWARNING("Cannot enable broadcasts on port %d (secondary): %d (%s)", m_Port, err, evutil_socket_error_to_string(err)); + LOGWARNING( + "Cannot enable broadcasts on port %d (secondary): %d (%s)", + m_Port, + err, + evutil_socket_error_to_string(err) + ); } } return; @@ -356,10 +429,21 @@ void cUDPEndpointImpl::EnableBroadcasts(void) // Enable broadcasts on the secondary socket, if opened (use int, it worked for primary): if (UDPEndpointImplHelper::IsValidSocket(m_SecondarySock)) { - if (setsockopt(m_SecondarySock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char *>(&broadcastInt), sizeof(broadcastInt)) == -1) + if (setsockopt( + m_SecondarySock, + SOL_SOCKET, + SO_BROADCAST, + reinterpret_cast<const char *>(&broadcastInt), + sizeof(broadcastInt) + ) == -1) { int err = EVUTIL_SOCKET_ERROR(); - LOGWARNING("Cannot enable broadcasts on port %d (secondary): %d (%s)", m_Port, err, evutil_socket_error_to_string(err)); + LOGWARNING( + "Cannot enable broadcasts on port %d (secondary): %d (%s)", + m_Port, + err, + evutil_socket_error_to_string(err) + ); } } } @@ -392,8 +476,14 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) if (!UDPEndpointImplHelper::IsValidSocket(m_MainSock)) { err = EVUTIL_SOCKET_ERROR(); - m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot create UDP socket for port {}: {} ({})"), - a_Port, err, evutil_socket_error_to_string(err)) + m_Callbacks.OnError( + err, + fmt::format( + FMT_STRING("Cannot create UDP socket for port {}: {} ({})"), + a_Port, + err, + evutil_socket_error_to_string(err) + ) ); return; } @@ -403,8 +493,9 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) { err = EVUTIL_SOCKET_ERROR(); LOG("UDP Port %d cannot be made reusable: %d (%s). Restarting the server might not work.", - a_Port, err, evutil_socket_error_to_string(err) - ); + a_Port, + err, + evutil_socket_error_to_string(err)); } // Bind to all interfaces: @@ -415,8 +506,14 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) if (bind(m_MainSock, reinterpret_cast<const sockaddr *>(&name), sizeof(name)) != 0) { err = EVUTIL_SOCKET_ERROR(); - m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot bind UDP port {}: {} ({})"), - a_Port, err, evutil_socket_error_to_string(err)) + m_Callbacks.OnError( + err, + fmt::format( + FMT_STRING("Cannot bind UDP port {}: {} ({})"), + a_Port, + err, + evutil_socket_error_to_string(err) + ) ); evutil_closesocket(m_MainSock); return; @@ -426,22 +523,24 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) { // IPv6 socket created, switch it into "dualstack" mode: UInt32 Zero = 0; - #ifdef _WIN32 - // WinXP doesn't support this feature, so if the setting fails, create another socket later on: - int res = setsockopt(m_MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); - err = EVUTIL_SOCKET_ERROR(); - NeedsTwoSockets = ((res == SOCKET_ERROR) && (err == WSAENOPROTOOPT)); - #else +#ifdef _WIN32 + // WinXP doesn't support this feature, so if the setting fails, create another socket later on: + int res = setsockopt(m_MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); - #endif + err = EVUTIL_SOCKET_ERROR(); + NeedsTwoSockets = ((res == SOCKET_ERROR) && (err == WSAENOPROTOOPT)); +#else + setsockopt(m_MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&Zero), sizeof(Zero)); +#endif // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(m_MainSock) != 0) { - err = EVUTIL_SOCKET_ERROR(); + err = EVUTIL_SOCKET_ERROR(); LOG("UDP Port %d cannot be made reusable: %d (%s). Restarting the server might not work.", - a_Port, err, evutil_socket_error_to_string(err) - ); + a_Port, + err, + evutil_socket_error_to_string(err)); } // Bind to all interfaces: @@ -452,8 +551,14 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) if (bind(m_MainSock, reinterpret_cast<const sockaddr *>(&name), sizeof(name)) != 0) { err = EVUTIL_SOCKET_ERROR(); - m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot bind to UDP port {}: {} ({})"), - a_Port, err, evutil_socket_error_to_string(err)) + m_Callbacks.OnError( + err, + fmt::format( + FMT_STRING("Cannot bind to UDP port {}: {} ({})"), + a_Port, + err, + evutil_socket_error_to_string(err) + ) ); evutil_closesocket(m_MainSock); return; @@ -462,13 +567,20 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) if (evutil_make_socket_nonblocking(m_MainSock) != 0) { err = EVUTIL_SOCKET_ERROR(); - m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot make socket on UDP port {} nonblocking: {} ({})"), - a_Port, err, evutil_socket_error_to_string(err)) + m_Callbacks.OnError( + err, + fmt::format( + FMT_STRING("Cannot make socket on UDP port {} nonblocking: {} ({})"), + a_Port, + err, + evutil_socket_error_to_string(err) + ) ); evutil_closesocket(m_MainSock); return; } - m_MainEvent = event_new(cNetworkSingleton::Get().GetEventBase(), m_MainSock, EV_READ | EV_PERSIST, RawCallback, this); + m_MainEvent = + event_new(cNetworkSingleton::Get().GetEventBase(), m_MainSock, EV_READ | EV_PERSIST, RawCallback, this); event_add(m_MainEvent, nullptr); // Read the actual port number on which the socket is listening: @@ -507,7 +619,12 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); - LOGD("Socket creation failed for secondary UDP socket for port %d: %d, %s", m_Port, err, evutil_socket_error_to_string(err)); + LOGD( + "Socket creation failed for secondary UDP socket for port %d: %d, %s", + m_Port, + err, + evutil_socket_error_to_string(err) + ); return; } @@ -516,8 +633,11 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); - LOGD("UDP Port %d cannot be made reusable (second socket): %d (%s). Restarting the server might not work.", - a_Port, err, evutil_socket_error_to_string(err) + LOGD( + "UDP Port %d cannot be made reusable (second socket): %d (%s). Restarting the server might not work.", + a_Port, + err, + evutil_socket_error_to_string(err) ); evutil_closesocket(m_SecondarySock); m_SecondarySock = -1; @@ -529,7 +649,11 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); - LOGD("evutil_make_socket_nonblocking() failed for secondary UDP socket: %d, %s", err, evutil_socket_error_to_string(err)); + LOGD( + "evutil_make_socket_nonblocking() failed for secondary UDP socket: %d, %s", + err, + evutil_socket_error_to_string(err) + ); evutil_closesocket(m_SecondarySock); m_SecondarySock = -1; return; @@ -550,7 +674,8 @@ void cUDPEndpointImpl::Open(UInt16 a_Port) return; } - m_SecondaryEvent = event_new(cNetworkSingleton::Get().GetEventBase(), m_SecondarySock, EV_READ | EV_PERSIST, RawCallback, this); + m_SecondaryEvent = + event_new(cNetworkSingleton::Get().GetEventBase(), m_SecondarySock, EV_READ | EV_PERSIST, RawCallback, this); event_add(m_SecondaryEvent, nullptr); } @@ -621,7 +746,3 @@ cUDPEndpointPtr cNetwork::CreateUDPEndpoint(UInt16 a_Port, cUDPEndpoint::cCallba { return std::make_shared<cUDPEndpointImpl>(a_Port, a_Callbacks); } - - - - diff --git a/src/OSSupport/UDPEndpointImpl.h b/src/OSSupport/UDPEndpointImpl.h index 32263d388..a9c49b506 100644 --- a/src/OSSupport/UDPEndpointImpl.h +++ b/src/OSSupport/UDPEndpointImpl.h @@ -24,13 +24,11 @@ typedef std::shared_ptr<cUDPEndpointImpl> cUDPEndpointImplPtr; -class cUDPEndpointImpl: - public cUDPEndpoint +class cUDPEndpointImpl : public cUDPEndpoint { using Super = cUDPEndpoint; -public: - + public: /** Creates a new instance of the endpoint, with the specified callbacks. Tries to open on the specified port; if it fails, the endpoint is left in the "closed" state. If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. */ @@ -45,7 +43,7 @@ public: virtual bool Send(const AString & a_Payload, const AString & a_Host, UInt16 a_Port) override; virtual void EnableBroadcasts(void) override; -protected: + protected: /** The local port on which the endpoint is open. If this is zero, it means the endpoint is closed - either opening has failed, or it has been closed explicitly. */ UInt16 m_Port; @@ -68,7 +66,8 @@ protected: /** Creates and opens the socket on the specified port. If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. - If the opening fails, the OnError() callback is called and the endpoint is left "closed" (IsOpen() returns false). */ + If the opening fails, the OnError() callback is called and the endpoint is left "closed" (IsOpen() returns false). + */ void Open(UInt16 a_Port); /** The callback that LibEvent calls when an event occurs on one of the sockets. @@ -78,7 +77,3 @@ protected: /** The callback that is called when an event occurs on one of the sockets. */ void Callback(evutil_socket_t a_Socket, short a_What); }; - - - - diff --git a/src/OSSupport/WinStackWalker.cpp b/src/OSSupport/WinStackWalker.cpp index a48ce07aa..93c1e4977 100644 --- a/src/OSSupport/WinStackWalker.cpp +++ b/src/OSSupport/WinStackWalker.cpp @@ -46,14 +46,14 @@ NOTE: 2017-06-16 madmaxoft: Removed the legacy VS code and generally cleaned up #include <tchar.h> #pragma comment(lib, "version.lib") // for "VerQueryValue" -#pragma warning(disable:4826) -#pragma warning(disable:4996) // "GetVersionEx" was declared deprecated +#pragma warning(disable : 4826) +#pragma warning(disable : 4996) // "GetVersionEx" was declared deprecated #include "WinStackWalker.h" #pragma pack(push, 8) - #include <dbghelp.h> +#include <dbghelp.h> #pragma pack(pop) @@ -61,8 +61,7 @@ NOTE: 2017-06-16 madmaxoft: Removed the legacy VS code and generally cleaned up // Copy szSrc to szDest, but at most nMaxDestSize bytes. Always NUL-terminate -template<size_t COUNT> -static void MyStrCpy(CHAR (&szDest)[COUNT], const CHAR * szSrc) +template <size_t COUNT> static void MyStrCpy(CHAR (&szDest)[COUNT], const CHAR * szSrc) { auto len = strlen(szSrc); if (len < COUNT) @@ -89,7 +88,7 @@ static void MyStrCpy(CHAR (&szDest)[COUNT], const CHAR * szSrc) class StackWalkerInternal { -public: + public: StackWalkerInternal(WinStackWalker * parent, HANDLE hProcess) { m_parent = parent; @@ -147,41 +146,45 @@ public: _tcscat_s(szTemp, _T(".local")); if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES) { - // ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows" - // Ok, first try the new path according to the archtitecture: - #ifdef _M_IX86 - if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) +// ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows" +// Ok, first try the new path according to the archtitecture: +#ifdef _M_IX86 + if ((m_hDbhHelp == nullptr) && + (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + { + _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x86)\\dbghelp.dll")); + // now check if the file exists: + if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x86)\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } + m_hDbhHelp = LoadLibrary(szTemp); } - #elif _M_X64 - if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + } +#elif _M_X64 + if ((m_hDbhHelp == nullptr) && + (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + { + _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x64)\\dbghelp.dll")); + // now check if the file exists: + if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x64)\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } + m_hDbhHelp = LoadLibrary(szTemp); } - #elif _M_IA64 - if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + } +#elif _M_IA64 + if ((m_hDbhHelp == nullptr) && + (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + { + _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (ia64)\\dbghelp.dll")); + // now check if the file exists: + if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (ia64)\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } + m_hDbhHelp = LoadLibrary(szTemp); } - #endif + } +#endif // If still not found, try the old directories... - if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + if ((m_hDbhHelp == nullptr) && + (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) { _tcscat_s(szTemp, _T("\\Debugging Tools for Windows\\dbghelp.dll")); // now check if the file exists: @@ -190,17 +193,18 @@ public: m_hDbhHelp = LoadLibrary(szTemp); } } - #if defined _M_X64 || defined _M_IA64 - // Still not found? Then try to load the (old) 64-Bit version: - if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) +#if defined _M_X64 || defined _M_IA64 + // Still not found? Then try to load the (old) 64-Bit version: + if ((m_hDbhHelp == nullptr) && + (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) + { + _tcscat_s(szTemp, _T("\\Debugging Tools for Windows 64-Bit\\dbghelp.dll")); + if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows 64-Bit\\dbghelp.dll")); - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } + m_hDbhHelp = LoadLibrary(szTemp); } - #endif + } +#endif } } if (m_hDbhHelp == nullptr) // if not already loaded, try to load a default-one @@ -211,28 +215,26 @@ public: { return FALSE; } - pSI = (tSI)GetProcAddress(m_hDbhHelp, "SymInitialize"); - pSC = (tSC)GetProcAddress(m_hDbhHelp, "SymCleanup"); + pSI = (tSI) GetProcAddress(m_hDbhHelp, "SymInitialize"); + pSC = (tSC) GetProcAddress(m_hDbhHelp, "SymCleanup"); - pSW = (tSW)GetProcAddress(m_hDbhHelp, "StackWalk64"); - pSGO = (tSGO)GetProcAddress(m_hDbhHelp, "SymGetOptions"); - pSSO = (tSSO)GetProcAddress(m_hDbhHelp, "SymSetOptions"); + pSW = (tSW) GetProcAddress(m_hDbhHelp, "StackWalk64"); + pSGO = (tSGO) GetProcAddress(m_hDbhHelp, "SymGetOptions"); + pSSO = (tSSO) GetProcAddress(m_hDbhHelp, "SymSetOptions"); - pSFTA = (tSFTA)GetProcAddress(m_hDbhHelp, "SymFunctionTableAccess64"); - pSGLFA = (tSGLFA)GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64"); - pSGMB = (tSGMB)GetProcAddress(m_hDbhHelp, "SymGetModuleBase64"); - pSGMI = (tSGMI)GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64"); + pSFTA = (tSFTA) GetProcAddress(m_hDbhHelp, "SymFunctionTableAccess64"); + pSGLFA = (tSGLFA) GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64"); + pSGMB = (tSGMB) GetProcAddress(m_hDbhHelp, "SymGetModuleBase64"); + pSGMI = (tSGMI) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64"); // pSGMI_V3 = (tSGMI_V3) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64"); - pSGSFA = (tSGSFA)GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64"); - pUDSN = (tUDSN)GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName"); - pSLM = (tSLM)GetProcAddress(m_hDbhHelp, "SymLoadModule64"); - pSGSP = (tSGSP)GetProcAddress(m_hDbhHelp, "SymGetSearchPath"); - - if ( - (pSC == nullptr) || (pSFTA == nullptr) || (pSGMB == nullptr) || (pSGMI == nullptr) || - (pSGO == nullptr) || (pSGSFA == nullptr) || (pSI == nullptr) || (pSSO == nullptr) || - (pSW == nullptr) || (pUDSN == nullptr) || (pSLM == nullptr) - ) + pSGSFA = (tSGSFA) GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64"); + pUDSN = (tUDSN) GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName"); + pSLM = (tSLM) GetProcAddress(m_hDbhHelp, "SymLoadModule64"); + pSGSP = (tSGSP) GetProcAddress(m_hDbhHelp, "SymGetSearchPath"); + + if ((pSC == nullptr) || (pSFTA == nullptr) || (pSGMB == nullptr) || (pSGMI == nullptr) || (pSGO == nullptr) || + (pSGSFA == nullptr) || (pSI == nullptr) || (pSSO == nullptr) || (pSW == nullptr) || (pUDSN == nullptr) || + (pSLM == nullptr)) { FreeLibrary(m_hDbhHelp); m_hDbhHelp = nullptr; @@ -255,7 +257,7 @@ public: symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS; symOptions = this->pSSO(symOptions); - char buf[WinStackWalker::STACKWALK_MAX_NAMELEN] = { 0 }; + char buf[WinStackWalker::STACKWALK_MAX_NAMELEN] = {0}; if (this->pSGSP != nullptr) { if (this->pSGSP(m_hProcess, buf, static_cast<DWORD>(sizeof(buf))) == FALSE) @@ -263,7 +265,7 @@ public: this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0); } } - char szUserName[1024] = { 0 }; + char szUserName[1024] = {0}; DWORD dwSize = static_cast<DWORD>(sizeof(szUserName)); GetUserNameA(szUserName, &dwSize); this->m_parent->OnSymInit(buf, symOptions, szUserName); @@ -281,69 +283,86 @@ public: HANDLE m_hProcess; LPSTR m_szSymPath; - #pragma pack(push, 8) +#pragma pack(push, 8) struct IMAGEHLP_MODULE64_V2 { - DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) - DWORD64 BaseOfImage; // base load address of module - DWORD ImageSize; // virtual size of the loaded module - DWORD TimeDateStamp; // date / time stamp from pe header - DWORD CheckSum; // checksum from the pe header - DWORD NumSyms; // number of symbols in the symbol table - SYM_TYPE SymType; // type of symbols loaded - CHAR ModuleName[32]; // module name - CHAR ImageName[256]; // image name - CHAR LoadedImageName[256]; // symbol file name + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date / time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + CHAR ModuleName[32]; // module name + CHAR ImageName[256]; // image name + CHAR LoadedImageName[256]; // symbol file name }; - #pragma pack(pop) +#pragma pack(pop) // SymCleanup() - typedef BOOL(__stdcall *tSC)(IN HANDLE hProcess); + typedef BOOL(__stdcall * tSC)(IN HANDLE hProcess); tSC pSC; // SymFunctionTableAccess64() - typedef PVOID(__stdcall *tSFTA)(HANDLE hProcess, DWORD64 AddrBase); + typedef PVOID(__stdcall * tSFTA)(HANDLE hProcess, DWORD64 AddrBase); tSFTA pSFTA; // SymGetLineFromAddr64() - typedef BOOL(__stdcall *tSGLFA)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line); + typedef BOOL(__stdcall * tSGLFA)( + IN HANDLE hProcess, + IN DWORD64 dwAddr, + OUT PDWORD pdwDisplacement, + OUT PIMAGEHLP_LINE64 Line + ); tSGLFA pSGLFA; // SymGetModuleBase64() - typedef DWORD64(__stdcall *tSGMB)(IN HANDLE hProcess, IN DWORD64 dwAddr); + typedef DWORD64(__stdcall * tSGMB)(IN HANDLE hProcess, IN DWORD64 dwAddr); tSGMB pSGMB; // SymGetModuleInfo64() - typedef BOOL(__stdcall *tSGMI)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo); + typedef BOOL(__stdcall * tSGMI)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 * ModuleInfo); tSGMI pSGMI; - // // SymGetModuleInfo64() - // typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo); - // tSGMI_V3 pSGMI_V3; + // // SymGetModuleInfo64() + // typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo); + // tSGMI_V3 pSGMI_V3; // SymGetOptions() - typedef DWORD(__stdcall *tSGO)(VOID); + typedef DWORD(__stdcall * tSGO)(VOID); tSGO pSGO; // SymGetSymFromAddr64() - typedef BOOL(__stdcall *tSGSFA)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol); + typedef BOOL(__stdcall * tSGSFA)( + IN HANDLE hProcess, + IN DWORD64 dwAddr, + OUT PDWORD64 pdwDisplacement, + OUT PIMAGEHLP_SYMBOL64 Symbol + ); tSGSFA pSGSFA; // SymInitialize() - typedef BOOL(__stdcall *tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess); + typedef BOOL(__stdcall * tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess); tSI pSI; // SymLoadModule64() - typedef DWORD64(__stdcall *tSLM)(IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll); + typedef DWORD64(__stdcall * tSLM)( + IN HANDLE hProcess, + IN HANDLE hFile, + IN PSTR ImageName, + IN PSTR ModuleName, + IN DWORD64 BaseOfDll, + IN DWORD SizeOfDll + ); tSLM pSLM; // SymSetOptions() - typedef DWORD(__stdcall *tSSO)(IN DWORD SymOptions); + typedef DWORD(__stdcall * tSSO)(IN DWORD SymOptions); tSSO pSSO; // StackWalk64() - typedef BOOL(__stdcall *tSW)( + typedef BOOL(__stdcall * tSW)( DWORD MachineType, HANDLE hProcess, HANDLE hThread, @@ -352,51 +371,53 @@ public: PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, - PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress + ); tSW pSW; // UnDecorateSymbolName() - typedef DWORD(__stdcall WINAPI *tUDSN)(PCSTR DecoratedName, PSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags); + typedef DWORD(__stdcall WINAPI * + tUDSN)(PCSTR DecoratedName, PSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags); tUDSN pUDSN; - typedef BOOL(__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength); + typedef BOOL(__stdcall WINAPI * tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength); tSGSP pSGSP; -private: - // **************************************** ToolHelp32 ************************ - #define MAX_MODULE_NAME32 255 - #define TH32CS_SNAPMODULE 0x00000008 + private: +// **************************************** ToolHelp32 ************************ +#define MAX_MODULE_NAME32 255 +#define TH32CS_SNAPMODULE 0x00000008 - #pragma pack(push, 8) +#pragma pack(push, 8) typedef struct tagMODULEENTRY32 { - DWORD dwSize; - DWORD th32ModuleID; // This module - DWORD th32ProcessID; // owning process - DWORD GlblcntUsage; // Global usage count on the module - DWORD ProccntUsage; // Module usage count in th32ProcessID's context - BYTE * modBaseAddr; // Base address of module in th32ProcessID's context - DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr - HMODULE hModule; // The hModule of this module in th32ProcessID's context - char szModule[MAX_MODULE_NAME32 + 1]; - char szExePath[MAX_PATH]; + DWORD dwSize; + DWORD th32ModuleID; // This module + DWORD th32ProcessID; // owning process + DWORD GlblcntUsage; // Global usage count on the module + DWORD ProccntUsage; // Module usage count in th32ProcessID's context + BYTE * modBaseAddr; // Base address of module in th32ProcessID's context + DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr + HMODULE hModule; // The hModule of this module in th32ProcessID's context + char szModule[MAX_MODULE_NAME32 + 1]; + char szExePath[MAX_PATH]; } MODULEENTRY32; - typedef MODULEENTRY32 * PMODULEENTRY32; - typedef MODULEENTRY32 * LPMODULEENTRY32; - #pragma pack(pop) + typedef MODULEENTRY32 * PMODULEENTRY32; + typedef MODULEENTRY32 * LPMODULEENTRY32; +#pragma pack(pop) BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid) { // CreateToolhelp32Snapshot() - typedef HANDLE(__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID); + typedef HANDLE(__stdcall * tCT32S)(DWORD dwFlags, DWORD th32ProcessID); // Module32First() - typedef BOOL(__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); + typedef BOOL(__stdcall * tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); // Module32Next() - typedef BOOL(__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); + typedef BOOL(__stdcall * tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); // try both dlls... - const TCHAR *dllname[] = { _T("kernel32.dll"), _T("tlhelp32.dll") }; + const TCHAR * dllname[] = {_T("kernel32.dll"), _T("tlhelp32.dll")}; HINSTANCE hToolhelp = nullptr; tCT32S pCT32S = nullptr; tM32F pM32F = nullptr; @@ -414,9 +435,9 @@ private: { continue; } - pCT32S = (tCT32S)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot"); - pM32F = (tM32F)GetProcAddress(hToolhelp, "Module32First"); - pM32N = (tM32N)GetProcAddress(hToolhelp, "Module32Next"); + pCT32S = (tCT32S) GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot"); + pM32F = (tM32F) GetProcAddress(hToolhelp, "Module32First"); + pM32N = (tM32N) GetProcAddress(hToolhelp, "Module32Next"); if ((pCT32S != nullptr) && (pM32F != nullptr) && (pM32N != nullptr)) { break; // found the functions! @@ -431,7 +452,7 @@ private: } hSnap = pCT32S(TH32CS_SNAPMODULE, pid); - if (hSnap == (HANDLE)-1) + if (hSnap == (HANDLE) -1) { FreeLibrary(hToolhelp); return FALSE; @@ -441,7 +462,7 @@ private: int cnt = 0; while (keepGoing) { - this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64)me.modBaseAddr, me.modBaseSize); + this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64) me.modBaseAddr, me.modBaseSize); cnt++; keepGoing = !!pM32N(hSnap, &me); } @@ -469,13 +490,13 @@ private: BOOL GetModuleListPSAPI(HANDLE hProcess) { // EnumProcessModules() - typedef BOOL(__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded); + typedef BOOL(__stdcall * tEPM)(HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); // GetModuleFileNameEx() - typedef DWORD(__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); + typedef DWORD(__stdcall * tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); // GetModuleBaseName() - typedef DWORD(__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); + typedef DWORD(__stdcall * tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); // GetModuleInformation() - typedef BOOL(__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize); + typedef BOOL(__stdcall * tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize); HINSTANCE hPsapi; tEPM pEPM; @@ -486,9 +507,9 @@ private: DWORD i; DWORD cbNeeded; MODULEINFO mi; - HMODULE *hMods = 0; - char *tt = nullptr; - char *tt2 = nullptr; + HMODULE * hMods = 0; + char * tt = nullptr; + char * tt2 = nullptr; const SIZE_T TTBUFLEN = 8096; int cnt = 0; @@ -498,10 +519,10 @@ private: return FALSE; } - pEPM = (tEPM)GetProcAddress(hPsapi, "EnumProcessModules"); - pGMFNE = (tGMFNE)GetProcAddress(hPsapi, "GetModuleFileNameExA"); - pGMBN = (tGMFNE)GetProcAddress(hPsapi, "GetModuleBaseNameA"); - pGMI = (tGMI)GetProcAddress(hPsapi, "GetModuleInformation"); + pEPM = (tEPM) GetProcAddress(hPsapi, "EnumProcessModules"); + pGMFNE = (tGMFNE) GetProcAddress(hPsapi, "GetModuleFileNameExA"); + pGMBN = (tGMFNE) GetProcAddress(hPsapi, "GetModuleBaseNameA"); + pGMI = (tGMI) GetProcAddress(hPsapi, "GetModuleInformation"); if ((pEPM == nullptr) || (pGMFNE == nullptr) || (pGMBN == nullptr) || (pGMI == nullptr)) { // we couldn't find all functions @@ -509,9 +530,9 @@ private: return FALSE; } - hMods = (HMODULE*)malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE)); - tt = (char*)malloc(sizeof(char) * TTBUFLEN); - tt2 = (char*)malloc(sizeof(char) * TTBUFLEN); + hMods = (HMODULE *) malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE)); + tt = (char *) malloc(sizeof(char) * TTBUFLEN); + tt2 = (char *) malloc(sizeof(char) * TTBUFLEN); if ((hMods == nullptr) || (tt == nullptr) || (tt2 == nullptr)) { goto cleanup; @@ -538,7 +559,7 @@ private: tt2[0] = 0; pGMBN(hProcess, hMods[i], tt2, TTBUFLEN); - DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64)mi.lpBaseOfDll, mi.SizeOfImage); + DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64) mi.lpBaseOfDll, mi.SizeOfImage); if (dwRes != ERROR_SUCCESS) { this->m_parent->OnDbgHelpErr("LoadModule", dwRes, 0); @@ -546,7 +567,7 @@ private: cnt++; } - cleanup: + cleanup: if (hPsapi != nullptr) { FreeLibrary(hPsapi); @@ -573,8 +594,8 @@ private: DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size) { - CHAR *szImg = _strdup(img); - CHAR *szMod = _strdup(mod); + CHAR * szImg = _strdup(img); + CHAR * szMod = _strdup(mod); DWORD result = ERROR_SUCCESS; if ((szImg == nullptr) || (szMod == nullptr)) { @@ -593,7 +614,7 @@ private: // try to retrive the file-version: if ((this->m_parent->m_options & WinStackWalker::RetrieveFileVersion) != 0) { - VS_FIXEDFILEINFO *fInfo = nullptr; + VS_FIXEDFILEINFO * fInfo = nullptr; DWORD dwHandle; DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle); if (dwSize > 0) @@ -605,13 +626,14 @@ private: { UINT len; TCHAR szSubBlock[] = _T("\\"); - if (VerQueryValue(vData, szSubBlock, (LPVOID*)&fInfo, &len) == 0) + if (VerQueryValue(vData, szSubBlock, (LPVOID *) &fInfo, &len) == 0) { fInfo = nullptr; } else { - fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32); + fileVersion = + ((ULONGLONG) fInfo->dwFileVersionLS) + ((ULONGLONG) fInfo->dwFileVersionMS << 32); } } free(vData); @@ -621,23 +643,24 @@ private: // Retrive some additional-infos about the module IMAGEHLP_MODULE64_V2 Module; - const char *szSymType = "-unknown-"; + const char * szSymType = "-unknown-"; if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE) { switch (Module.SymType) { - case SymNone: szSymType = "-nosymbols-"; break; - case SymCoff: szSymType = "COFF"; break; - case SymCv: szSymType = "CV"; break; - case SymPdb: szSymType = "PDB"; break; - case SymExport: szSymType = "-exported-"; break; + case SymNone: szSymType = "-nosymbols-"; break; + case SymCoff: szSymType = "COFF"; break; + case SymCv: szSymType = "CV"; break; + case SymPdb: szSymType = "PDB"; break; + case SymExport: szSymType = "-exported-"; break; case SymDeferred: szSymType = "-deferred-"; break; case SymSym: szSymType = "SYM"; break; case 7: szSymType = "DIA"; break; case 8: szSymType = "Virtual"; break; } } - this->m_parent->OnLoadModule(img, mod, baseAddr, size, result, szSymType, Module.LoadedImageName, fileVersion); + this->m_parent + ->OnLoadModule(img, mod, baseAddr, size, result, szSymType, Module.LoadedImageName, fileVersion); } if (szImg != nullptr) { @@ -654,7 +677,7 @@ private: -public: + public: BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId) { // first try toolhelp32 @@ -667,7 +690,7 @@ public: } - BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V2 *pModuleInfo) + BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V2 * pModuleInfo) { if (this->pSGMI == nullptr) { @@ -675,14 +698,15 @@ public: return FALSE; } pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); - void * pData = malloc(4096); // reserve enough memory, so the bug in v6.3.5.1 does not lead to memory-overwrites... + void * pData = + malloc(4096); // reserve enough memory, so the bug in v6.3.5.1 does not lead to memory-overwrites... if (pData == nullptr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V2)); - if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V2*)pData) != FALSE) + if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V2 *) pData) != FALSE) { // only copy as much memory as is reserved... memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V2)); @@ -770,11 +794,11 @@ BOOL WinStackWalker::LoadModules() } // Build the sym-path: - char *szSymPath = nullptr; + char * szSymPath = nullptr; if ((this->m_options & SymBuildPath) != 0) { const size_t nSymPathLen = 4096; - szSymPath = (char*)malloc(nSymPathLen); + szSymPath = (char *) malloc(nSymPathLen); if (szSymPath == nullptr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); @@ -804,7 +828,7 @@ BOOL WinStackWalker::LoadModules() if (GetModuleFileNameA(nullptr, szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; - for (char *p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) + for (char * p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) { // locate the rightmost path separator if ((*p == '\\') || (*p == '/') || (*p == ':')) @@ -893,11 +917,16 @@ BOOL WinStackWalker::LoadModules() static WinStackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = nullptr; static LPVOID s_readMemoryFunction_UserData = nullptr; -BOOL WinStackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) +BOOL WinStackWalker::ShowCallstack( + HANDLE hThread, + const CONTEXT * context, + PReadProcessMemoryRoutine readMemoryFunction, + LPVOID pUserData +) { CONTEXT c; CallstackEntry csEntry; - IMAGEHLP_SYMBOL64 *pSym = nullptr; + IMAGEHLP_SYMBOL64 * pSym = nullptr; StackWalkerInternal::IMAGEHLP_MODULE64_V2 Module; IMAGEHLP_LINE64 Line; int frameNum; @@ -946,38 +975,38 @@ BOOL WinStackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PRead STACKFRAME64 s; // in / out stackframe memset(&s, 0, sizeof(s)); DWORD imageType; - #ifdef _M_IX86 - // normally, call ImageNtHeader() and use machine info from PE header - imageType = IMAGE_FILE_MACHINE_I386; - s.AddrPC.Offset = c.Eip; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.Ebp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrStack.Offset = c.Esp; - s.AddrStack.Mode = AddrModeFlat; - #elif _M_X64 - imageType = IMAGE_FILE_MACHINE_AMD64; - s.AddrPC.Offset = c.Rip; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.Rsp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrStack.Offset = c.Rsp; - s.AddrStack.Mode = AddrModeFlat; - #elif _M_IA64 - imageType = IMAGE_FILE_MACHINE_IA64; - s.AddrPC.Offset = c.StIIP; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.IntSp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrBStore.Offset = c.RsBSP; - s.AddrBStore.Mode = AddrModeFlat; - s.AddrStack.Offset = c.IntSp; - s.AddrStack.Mode = AddrModeFlat; - #else - #error "Platform not supported!" - #endif - - pSym = (IMAGEHLP_SYMBOL64 *)malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); +#ifdef _M_IX86 + // normally, call ImageNtHeader() and use machine info from PE header + imageType = IMAGE_FILE_MACHINE_I386; + s.AddrPC.Offset = c.Eip; + s.AddrPC.Mode = AddrModeFlat; + s.AddrFrame.Offset = c.Ebp; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrStack.Offset = c.Esp; + s.AddrStack.Mode = AddrModeFlat; +#elif _M_X64 + imageType = IMAGE_FILE_MACHINE_AMD64; + s.AddrPC.Offset = c.Rip; + s.AddrPC.Mode = AddrModeFlat; + s.AddrFrame.Offset = c.Rsp; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrStack.Offset = c.Rsp; + s.AddrStack.Mode = AddrModeFlat; +#elif _M_IA64 + imageType = IMAGE_FILE_MACHINE_IA64; + s.AddrPC.Offset = c.StIIP; + s.AddrPC.Mode = AddrModeFlat; + s.AddrFrame.Offset = c.IntSp; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrBStore.Offset = c.RsBSP; + s.AddrBStore.Mode = AddrModeFlat; + s.AddrStack.Offset = c.IntSp; + s.AddrStack.Mode = AddrModeFlat; +#else +#error "Platform not supported!" +#endif + + pSym = (IMAGEHLP_SYMBOL64 *) malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); if (!pSym) { goto cleanup; // not enough memory... @@ -992,14 +1021,24 @@ BOOL WinStackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PRead memset(&Module, 0, sizeof(Module)); Module.SizeOfStruct = sizeof(Module); - for (frameNum = 0; ; ++frameNum) + for (frameNum = 0;; ++frameNum) { // get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64()) // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can // assume that either you are done, or that the stack is so hosed that the next // deeper frame could not be found. // CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386! - if (!this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, nullptr)) + if (!this->m_sw->pSW( + imageType, + this->m_hProcess, + hThread, + &s, + &c, + myReadProcMem, + this->m_sw->pSFTA, + this->m_sw->pSGMB, + nullptr + )) { // INFO: "StackWalk64" does not set "GetLastError"... this->OnDbgHelpErr("StackWalk64", 0, s.AddrPC.Offset); @@ -1037,8 +1076,18 @@ BOOL WinStackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PRead { MyStrCpy(csEntry.name, pSym->Name); // UnDecorateSymbolName() - this->m_sw->pUDSN(pSym->Name, csEntry.undName, static_cast<DWORD>(sizeof(csEntry.undName)), UNDNAME_NAME_ONLY); - this->m_sw->pUDSN(pSym->Name, csEntry.undFullName, static_cast<DWORD>(sizeof(csEntry.undFullName)), UNDNAME_COMPLETE); + this->m_sw->pUDSN( + pSym->Name, + csEntry.undName, + static_cast<DWORD>(sizeof(csEntry.undName)), + UNDNAME_NAME_ONLY + ); + this->m_sw->pUDSN( + pSym->Name, + csEntry.undFullName, + static_cast<DWORD>(sizeof(csEntry.undFullName)), + UNDNAME_COMPLETE + ); } else { @@ -1127,24 +1176,32 @@ cleanup: BOOL __stdcall WinStackWalker::myReadProcMem( - HANDLE hProcess, - DWORD64 qwBaseAddress, - PVOID lpBuffer, - DWORD nSize, - LPDWORD lpNumberOfBytesRead + HANDLE hProcess, + DWORD64 qwBaseAddress, + PVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead ) { if (s_readMemoryFunction == nullptr) { SIZE_T st; - BOOL bRet = ReadProcessMemory(hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, &st); - *lpNumberOfBytesRead = (DWORD)st; - // printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet); + BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st); + *lpNumberOfBytesRead = (DWORD) st; + // printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, + // (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet); return bRet; } else { - return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData); + return s_readMemoryFunction( + hProcess, + qwBaseAddress, + lpBuffer, + nSize, + lpNumberOfBytesRead, + s_readMemoryFunction_UserData + ); } } @@ -1152,7 +1209,16 @@ BOOL __stdcall WinStackWalker::myReadProcMem( -void WinStackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion) +void WinStackWalker::OnLoadModule( + LPCSTR img, + LPCSTR mod, + DWORD64 baseAddr, + DWORD size, + DWORD result, + LPCSTR symType, + LPCSTR pdbName, + ULONGLONG fileVersion +) { /* // Uncomment to be notified of loaded DLL modules. @@ -1160,7 +1226,8 @@ void WinStackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWOR char buffer[STACKWALK_MAX_NAMELEN]; if (fileVersion == 0) { - _snprintf_s(buffer, sizeof(buffer), "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, (LPVOID)baseAddr, size, result, symType, pdbName); + _snprintf_s(buffer, sizeof(buffer), "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, + (LPVOID)baseAddr, size, result, symType, pdbName); } else { @@ -1168,7 +1235,8 @@ void WinStackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWOR DWORD v3 = (DWORD)(fileVersion >> 16) & 0xFFFF; DWORD v2 = (DWORD)(fileVersion >> 32) & 0xFFFF; DWORD v1 = (DWORD)(fileVersion >> 48) & 0xFFFF; - _snprintf_s(buffer, sizeof(buffer), "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", img, mod, (LPVOID)baseAddr, size, result, symType, pdbName, v1, v2, v3, v4); + _snprintf_s(buffer, sizeof(buffer), "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: + %d.%d.%d.%d\n", img, mod, (LPVOID)baseAddr, size, result, symType, pdbName, v1, v2, v3, v4); } OnOutput(buffer); */ @@ -1178,7 +1246,7 @@ void WinStackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWOR -void WinStackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry) +void WinStackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry & entry) { CHAR buffer[STACKWALK_MAX_NAMELEN + MAX_PATH + 100]; if ((eType == lastEntry) || (entry.offset == 0)) @@ -1204,7 +1272,15 @@ void WinStackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry & { MyStrCpy(entry.moduleName, "(module-name not available)"); } - _snprintf_s(buffer, sizeof(buffer), "%p (%s): %s: %s\n", (LPVOID)entry.offset, entry.moduleName, entry.lineFileName, entry.name); + _snprintf_s( + buffer, + sizeof(buffer), + "%p (%s): %s: %s\n", + (LPVOID) entry.offset, + entry.moduleName, + entry.lineFileName, + entry.name + ); } else { @@ -1220,7 +1296,7 @@ void WinStackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry & void WinStackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr) { CHAR buffer[STACKWALK_MAX_NAMELEN]; - _snprintf_s(buffer, sizeof(buffer), "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID)addr); + _snprintf_s(buffer, sizeof(buffer), "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID) addr); OnOutput(buffer); } @@ -1231,17 +1307,31 @@ void WinStackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr) void WinStackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName) { CHAR buffer[STACKWALK_MAX_NAMELEN]; - _snprintf_s(buffer, sizeof(buffer), "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", szSearchPath, symOptions, szUserName); + _snprintf_s( + buffer, + sizeof(buffer), + "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", + szSearchPath, + symOptions, + szUserName + ); OnOutput(buffer); // Also display the OS-version OSVERSIONINFOEXA ver; ZeroMemory(&ver, sizeof(OSVERSIONINFOEXA)); ver.dwOSVersionInfoSize = sizeof(ver); - if (GetVersionExA((OSVERSIONINFOA*)&ver) != FALSE) + if (GetVersionExA((OSVERSIONINFOA *) &ver) != FALSE) { - _snprintf_s(buffer, sizeof(buffer), "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n", - ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber, - ver.szCSDVersion, ver.wSuiteMask, ver.wProductType + _snprintf_s( + buffer, + sizeof(buffer), + "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n", + ver.dwMajorVersion, + ver.dwMinorVersion, + ver.dwBuildNumber, + ver.szCSDVersion, + ver.wSuiteMask, + ver.wProductType ); OnOutput(buffer); } diff --git a/src/OSSupport/WinStackWalker.h b/src/OSSupport/WinStackWalker.h index 0479bd17b..002efa711 100644 --- a/src/OSSupport/WinStackWalker.h +++ b/src/OSSupport/WinStackWalker.h @@ -46,7 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class StackWalkerInternal; // forward class WinStackWalker { -public: + public: enum StackWalkOptions { // No addition info will be retrived @@ -91,31 +91,31 @@ public: WinStackWalker(DWORD dwProcessId, HANDLE hProcess); virtual ~WinStackWalker(); - typedef BOOL(__stdcall *PReadProcessMemoryRoutine)( - HANDLE hProcess, - DWORD64 qwBaseAddress, - PVOID lpBuffer, - DWORD nSize, - LPDWORD lpNumberOfBytesRead, - LPVOID pUserData // optional data, which was passed in "ShowCallstack" + typedef BOOL(__stdcall * PReadProcessMemoryRoutine)( + HANDLE hProcess, + DWORD64 qwBaseAddress, + PVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead, + LPVOID pUserData // optional data, which was passed in "ShowCallstack" ); BOOL LoadModules(); BOOL ShowCallstack( HANDLE hThread = GetCurrentThread(), - const CONTEXT *context = nullptr, + const CONTEXT * context = nullptr, PReadProcessMemoryRoutine readMemoryFunction = nullptr, LPVOID pUserData = nullptr // optional to identify some data in the 'readMemoryFunction'-callback ); -protected: + protected: enum { STACKWALK_MAX_NAMELEN = 1024, ///< Max name length for found symbols }; -protected: + protected: // Entry for each Callstack-Entry struct CallstackEntry { @@ -134,15 +134,29 @@ protected: CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; }; - enum CallstackEntryType { firstEntry, nextEntry, lastEntry }; + enum CallstackEntryType + { + firstEntry, + nextEntry, + lastEntry + }; virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); - virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion); - virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry); + virtual void OnLoadModule( + LPCSTR img, + LPCSTR mod, + DWORD64 baseAddr, + DWORD size, + DWORD result, + LPCSTR symType, + LPCSTR pdbName, + ULONGLONG fileVersion + ); + virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry & entry); virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr); virtual void OnOutput(LPCSTR szText); - StackWalkerInternal *m_sw; + StackWalkerInternal * m_sw; HANDLE m_hProcess; DWORD m_dwProcessId; BOOL m_modulesLoaded; @@ -151,7 +165,13 @@ protected: int m_options; int m_MaxRecursionCount; - static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead); + static BOOL __stdcall myReadProcMem( + HANDLE hProcess, + DWORD64 qwBaseAddress, + PVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead + ); friend StackWalkerInternal; }; @@ -160,12 +180,13 @@ protected: #define GET_CURRENT_CONTEXT(c, contextFlags) \ - do \ - { \ - memset(&c, 0, sizeof(CONTEXT)); \ - c.ContextFlags = contextFlags; \ - RtlCaptureContext(&c); \ - } while (false); + do \ + { \ + memset(&c, 0, sizeof(CONTEXT)); \ + c.ContextFlags = contextFlags; \ + RtlCaptureContext(&c); \ + } \ + while (false); |