You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
4.5 KiB
133 lines
4.5 KiB
#include <QApplication> |
|
#include <QPalette> |
|
#include <QStyleFactory> |
|
#include <QDir> |
|
#include <cstdio> |
|
#ifdef _WIN32 |
|
#include <windows.h> |
|
#include <tlhelp32.h> |
|
#endif |
|
#include "mainwindow.h" |
|
#include "../db/db_manager.h" |
|
#include "../transport/node_config.h" |
|
#include "../transport/utun_node.h" |
|
#include "../../lib/debug_config.h" |
|
|
|
#ifdef _WIN32 |
|
static UtunNode* g_ctrl_node = nullptr; |
|
|
|
static DWORD count_threads(void) { |
|
DWORD pid = GetCurrentProcessId(), count = 0; |
|
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); |
|
if (snap == INVALID_HANDLE_VALUE) return 0; |
|
THREADENTRY32 te = { sizeof(te) }; |
|
if (Thread32First(snap, &te)) { |
|
do { if (te.th32OwnerProcessID == pid) count++; } |
|
while (Thread32Next(snap, &te)); |
|
} |
|
CloseHandle(snap); |
|
return count; |
|
} |
|
|
|
static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType) { |
|
if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { |
|
if (g_ctrl_node) g_ctrl_node->requestStop(); |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
#endif |
|
|
|
static struct ShutdownSentinel { |
|
~ShutdownSentinel() { |
|
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "main: static destructors done"); |
|
#ifdef _WIN32 |
|
DWORD threads = count_threads(); |
|
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "main: threads at exit=%lu", (unsigned long)threads); |
|
if (threads > 4) { |
|
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "main: %lu hanging threads, TerminateProcess", (unsigned long)threads); |
|
fflush(nullptr); |
|
TerminateProcess(GetCurrentProcess(), 0); |
|
} |
|
#endif |
|
} |
|
} g_shutdown_sentinel; |
|
|
|
int main(int argc, char *argv[]) { |
|
QApplication app(argc, argv); |
|
app.setApplicationName("Chat"); |
|
app.setQuitOnLastWindowClosed(false); |
|
|
|
app.setStyle(QStyleFactory::create("Fusion")); |
|
QPalette p; |
|
p.setColor(QPalette::Window, QColor(53, 53, 53)); |
|
p.setColor(QPalette::WindowText, QColor(220, 220, 220)); |
|
p.setColor(QPalette::Base, QColor(42, 42, 42)); |
|
p.setColor(QPalette::AlternateBase, QColor(66, 66, 66)); |
|
p.setColor(QPalette::ToolTipBase, QColor(25, 25, 25)); |
|
p.setColor(QPalette::ToolTipText, QColor(220, 220, 220)); |
|
p.setColor(QPalette::Text, QColor(220, 220, 220)); |
|
p.setColor(QPalette::Button, QColor(53, 53, 53)); |
|
p.setColor(QPalette::ButtonText, QColor(220, 220, 220)); |
|
p.setColor(QPalette::BrightText, Qt::red); |
|
p.setColor(QPalette::Link, QColor(42, 130, 218)); |
|
p.setColor(QPalette::Highlight, QColor(42, 130, 218)); |
|
p.setColor(QPalette::HighlightedText, Qt::white); |
|
p.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); |
|
p.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); |
|
app.setPalette(p); |
|
|
|
QString cfgPath = QCoreApplication::applicationDirPath() + "/chatgui.cfg"; |
|
|
|
NodeConfig cfg(cfgPath); |
|
bool needSave = false; |
|
|
|
if (!cfg.exists()) { |
|
if (!cfg.create("chatgui", 1333)) { |
|
qCritical("Failed to create config: %s", qPrintable(cfgPath)); |
|
return 1; |
|
} |
|
} else { |
|
if (!cfg.load()) { |
|
qCritical("Cannot open/read config file: %s", qPrintable(cfgPath)); |
|
return 1; |
|
} |
|
if (cfg.hasErrors()) { |
|
for (const auto& err : cfg.errors()) |
|
fprintf(stderr, "CONFIG ERROR: %s\n", qPrintable(err)); |
|
return 1; |
|
} |
|
if (cfg.privKey().length() != 64 || cfg.pubKey().length() != 64) { |
|
qWarning("Config: keys missing/invalid, regenerating identity"); |
|
cfg.generateIdentity(); |
|
needSave = true; |
|
} |
|
if (cfg.nodeId().length() != 16) { |
|
qWarning("Config: my_node_id missing/invalid, regenerating identity"); |
|
cfg.generateIdentity(); |
|
needSave = true; |
|
} |
|
if (needSave) |
|
cfg.save(); |
|
} |
|
|
|
QString dbPath = cfg.dbPath(); |
|
if (dbPath.isEmpty()) dbPath = "chat_data"; |
|
if (!QDir::isAbsolutePath(dbPath)) |
|
dbPath = QCoreApplication::applicationDirPath() + "/" + dbPath; |
|
QDir(dbPath).mkpath("."); |
|
|
|
DbManager db; |
|
MainWindow w(nullptr, &db, cfgPath, dbPath, cfg.debugFile(), |
|
cfg.debugLevel(), cfg.debugCategories()); |
|
w.show(); |
|
|
|
#ifdef _WIN32 |
|
g_ctrl_node = w.utunNode(); |
|
SetConsoleCtrlHandler(console_ctrl_handler, TRUE); |
|
#endif |
|
|
|
int ret = app.exec(); |
|
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "main: app.exec() returned %d", ret); |
|
return ret; |
|
}
|
|
|