From 5eb614d94d8292ae62636b0d39f0ca627782a5a5 Mon Sep 17 00:00:00 2001 From: Edgar Date: Sat, 5 May 2018 21:12:52 +0200 Subject: [PATCH] :triangular_ruler: Reformated code --- CMakeLists.txt | 2 + source/common/UnicodeStrings.h | 180 +++--- source/gui/resource.h | 12 +- source/gui/servergui.cpp | 276 +++++---- source/gui/statpict.cpp | 89 +-- source/gui/statpict.h | 74 ++- source/protocol/rornet.h | 275 ++++----- source/server/ScriptEngine.cpp | 787 ++++++++++++++++--------- source/server/ScriptEngine.h | 75 +-- source/server/ScriptFileSafe.cpp | 440 +++++++++----- source/server/ScriptFileSafe.h | 43 +- source/server/broadcaster.cpp | 130 +++-- source/server/broadcaster.h | 71 +-- source/server/config.cpp | 771 +++++++++++++++--------- source/server/config.h | 60 +- source/server/http.cpp | 134 +++-- source/server/http.h | 81 +-- source/server/listener.cpp | 143 +++-- source/server/listener.h | 49 +- source/server/logger.cpp | 123 ++-- source/server/logger.h | 49 +- source/server/master-server.cpp | 119 ++-- source/server/master-server.h | 64 +- source/server/messaging.cpp | 204 ++++--- source/server/messaging.h | 69 ++- source/server/mongoose.h | 38 +- source/server/mutexutils.cpp | 175 ++++-- source/server/mutexutils.h | 82 +-- source/server/prerequisites.h | 3 +- source/server/receiver.cpp | 92 +-- source/server/receiver.h | 49 +- source/server/resource.h | 12 +- source/server/rorserver.cpp | 276 +++++---- source/server/sequencer.cpp | 973 +++++++++++++++++++------------ source/server/sequencer.h | 154 ++--- source/server/sha1.h | 19 +- source/server/sha1_util.cpp | 108 ++-- source/server/sha1config.h | 12 +- source/server/userauth.cpp | 356 +++++------ source/server/userauth.h | 45 +- source/server/utils.cpp | 140 +++-- source/server/utils.h | 51 +- source/server/webserver.cpp | 367 +++++++----- 43 files changed, 4272 insertions(+), 3000 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ae1ab84..4b413cbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ endif (COMMAND cmake_policy) project(rorserver) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + # setup paths SET(RUNTIME_OUTPUT_DIRECTORY "${rorserver_SOURCE_DIR}/bin/") SET(LIBRARY_OUTPUT_DIRECTORY "${rorserver_SOURCE_DIR}/lib/") diff --git a/source/common/UnicodeStrings.h b/source/common/UnicodeStrings.h index 70c99d11..a3376a80 100644 --- a/source/common/UnicodeStrings.h +++ b/source/common/UnicodeStrings.h @@ -20,7 +20,7 @@ /// char16_t, std::u16string = UTF-16LE (not UCS-2 -> 2 or 4 bytes!) /// char32_t, std::u32string = UTF-32LE /// wchar_t, std::wstring = Forbidden, except for using wchar APIs. -/// +/// /// Inspired by http://www.utf8everywhere.org /// /// CRASH COURSE OF TEXT PROCESSING @@ -56,95 +56,125 @@ #include #include -namespace Str { - -// UTF-8 byte signatures -// Spec: 0/1 are bit values, 'x' are codepoint bits -// -// type | spec | mask | value -// ----------------------------------- -// 1byte | 0xxxxxxx | 10000000 | 00000000 -// 2byte | 110xxxxx | 11100000 | 11000000 -// 3byte | 1110xxxx | 11110000 | 11100000 -// 4byte | 11110xxx | 11111000 | 11110000 -// cont. | 10xxxxxx | 11000000 | 10000000 - - static const char UTF8_SIG_LEAD_1b = '\x00'; - static const char UTF8_SIG_LEAD_2b = '\xC0'; - static const char UTF8_SIG_LEAD_3b = '\xE0'; - static const char UTF8_SIG_LEAD_4b = '\xF0'; - static const char UTF8_SIG_CONT = '\x80'; - static const char UTF8_MASK_LEAD_1b = '\x80'; - static const char UTF8_MASK_LEAD_2b = '\xE0'; - static const char UTF8_MASK_LEAD_3b = '\xF0'; - static const char UTF8_MASK_LEAD_4b = '\xF8'; - static const char UTF8_MASK_CONT = '\xC0'; - static const char *UTF8_REPLACEMENT_CHAR = u8"\uFFFD"; // The � REPLACEMENT CHARACTER - - inline bool IsUtf8Lead1b(const char c) { return (c & UTF8_MASK_LEAD_1b) == UTF8_SIG_LEAD_1b; } - - inline bool IsUtf8Lead2b(const char c) { return (c & UTF8_MASK_LEAD_2b) == UTF8_SIG_LEAD_2b; } - - inline bool IsUtf8Lead3b(const char c) { return (c & UTF8_MASK_LEAD_3b) == UTF8_SIG_LEAD_3b; } - - inline bool IsUtf8Lead4b(const char c) { return (c & UTF8_MASK_LEAD_4b) == UTF8_SIG_LEAD_4b; } - - inline bool IsUtf8Cont(const char c) { return (c & UTF8_MASK_CONT) == UTF8_SIG_CONT; } - -/// Mercilessly replaces all invalid code units with supplied sequence. -/// OctetIterator_T can be either STL iterator or plain old `const char*`. -/// @param OctetIterator_T start Start of source string. Required. -/// @param OctetIterator_T end End of source. Required. -/// @param const char* sub Substitute sequence; default: U+FFFD � REPLACEMENT CHARACTER. +namespace Str +{ + // UTF-8 byte signatures + // Spec: 0/1 are bit values, 'x' are codepoint bits + // + // type | spec | mask | value + // ----------------------------------- + // 1byte | 0xxxxxxx | 10000000 | 00000000 + // 2byte | 110xxxxx | 11100000 | 11000000 + // 3byte | 1110xxxx | 11110000 | 11100000 + // 4byte | 11110xxx | 11111000 | 11110000 + // cont. | 10xxxxxx | 11000000 | 10000000 + + static const char UTF8_SIG_LEAD_1b = '\x00'; + static const char UTF8_SIG_LEAD_2b = '\xC0'; + static const char UTF8_SIG_LEAD_3b = '\xE0'; + static const char UTF8_SIG_LEAD_4b = '\xF0'; + static const char UTF8_SIG_CONT = '\x80'; + static const char UTF8_MASK_LEAD_1b = '\x80'; + static const char UTF8_MASK_LEAD_2b = '\xE0'; + static const char UTF8_MASK_LEAD_3b = '\xF0'; + static const char UTF8_MASK_LEAD_4b = '\xF8'; + static const char UTF8_MASK_CONT = '\xC0'; + static const char *UTF8_REPLACEMENT_CHAR = u8"\uFFFD"; // The � REPLACEMENT CHARACTER + + inline bool IsUtf8Lead1b(const char c) + { + return (c & UTF8_MASK_LEAD_1b) == UTF8_SIG_LEAD_1b; + } + + inline bool IsUtf8Lead2b(const char c) + { + return (c & UTF8_MASK_LEAD_2b) == UTF8_SIG_LEAD_2b; + } + + inline bool IsUtf8Lead3b(const char c) + { + return (c & UTF8_MASK_LEAD_3b) == UTF8_SIG_LEAD_3b; + } + + inline bool IsUtf8Lead4b(const char c) + { + return (c & UTF8_MASK_LEAD_4b) == UTF8_SIG_LEAD_4b; + } + + inline bool IsUtf8Cont(const char c) + { + return (c & UTF8_MASK_CONT) == UTF8_SIG_CONT; + } + + /// Mercilessly replaces all invalid code units with supplied sequence. + /// OctetIterator_T can be either STL iterator or plain old `const char*`. + /// @param OctetIterator_T start Start of source string. Required. + /// @param OctetIterator_T end End of source. Required. + /// @param const char* sub Substitute sequence; default: U+FFFD � REPLACEMENT CHARACTER. template - std::string SanitizeUtf8(OctetIterator_T start, OctetIterator_T end, const char *sub = UTF8_REPLACEMENT_CHAR) { + std::string SanitizeUtf8(OctetIterator_T start, OctetIterator_T end, const char *sub = UTF8_REPLACEMENT_CHAR) + { std::string res; - char buffer[] = {'\0', '\0', '\0', '\0', '\0'}; // 4 octets + NULL terminator - int buffer_next = 0; // Next available octet slot - int buffer_max = 0; // Current character's declared number of octets. - for (OctetIterator_T pos = start; pos != end; ++pos) { - if (buffer_next == 0) // We're at lead byte and must detect. + char buffer[] = { '\0', '\0', '\0', '\0', '\0' }; // 4 octets + NULL terminator + int buffer_next = 0; // Next available octet slot + int buffer_max = 0; // Current character's declared number of octets. + + for (OctetIterator_T pos = start; pos != end; ++pos) + { + if (buffer_next == 0) // We're at lead byte and must detect. { - if (IsUtf8Lead1b(*pos)) { + if (IsUtf8Lead1b(*pos)) + { res += *pos; - } else if (IsUtf8Cont(*pos)) { + } + else if (IsUtf8Cont(*pos)) + { res += sub; - } else { - buffer_max = (IsUtf8Lead2b(*pos)) ? 2 : buffer_max; - buffer_max = (IsUtf8Lead3b(*pos)) ? 3 : buffer_max; - buffer_max = (IsUtf8Lead4b(*pos)) ? 4 : buffer_max; + } + else + { + buffer_max = (IsUtf8Lead2b(*pos)) ? 2 : buffer_max; + buffer_max = (IsUtf8Lead3b(*pos)) ? 3 : buffer_max; + buffer_max = (IsUtf8Lead4b(*pos)) ? 4 : buffer_max; buffer[buffer_next++] = *pos; } - } else { - if (IsUtf8Cont(*pos)) { + } + else + { + if (IsUtf8Cont(*pos)) + { buffer[buffer_next++] = *pos; - if (buffer_next == buffer_max) { + if (buffer_next == buffer_max) + { buffer[buffer_max] = '\0'; - res += buffer; - buffer_next = 0; + res += buffer; + buffer_next = 0; } - } else { - res += sub; + } + else + { + res += sub; buffer_next = 0; } } } - if (buffer_next != 0) { + if (buffer_next != 0) res += sub; - } - return res; // We rely on C++11's move semantics -> no copy here. + return res; // We rely on C++11's move semantics -> no copy here. } -/// Convenience overload for plain old NULL-terminated C-strings - inline std::string SanitizeUtf8(const char *str, const char *sub = UTF8_REPLACEMENT_CHAR) { + /// Convenience overload for plain old NULL-terminated C-strings + inline std::string SanitizeUtf8(const char *str, const char *sub = UTF8_REPLACEMENT_CHAR) + { return SanitizeUtf8(str, str + strlen(str), sub); } -/// Replicates behavior of `isspace()` under "C" locale - to be independent and faster. - inline bool IsWhitespaceAscii(char c) { - return (c == ' ') // (0x20) space (SPC) + /// Replicates behavior of `isspace()` under "C" locale - to be independent and faster. + inline bool IsWhitespaceAscii(char c) + { + return (c == ' ') // (0x20) space (SPC) || (c == '\t') // (0x09) horizontal tab (TAB) || (c == '\n') // (0x0a) newline (LF) || (c == '\v') // (0x0b) vertical tab (VT) @@ -152,15 +182,19 @@ namespace Str { || (c == '\r'); // (0x0d) carriage return (CR) } -// TODO: implement `TrimUtf8()`! -/// @param start Pointer to first character (or NUL-terminating character if the string is empty) -/// @param end Pointer to after-the-last character (the NUL-terminating character) - inline void TrimAscii(char *&start, char *&end) { + // TODO: implement `TrimUtf8()`! + /// @param start Pointer to first character (or NUL-terminating character if the string is empty) + /// @param end Pointer to after-the-last character (the NUL-terminating character) + inline void TrimAscii(char *&start, char *&end) + { while ((start != end) && IsWhitespaceAscii(*start)) + { ++start; + } while ((start != end) && IsWhitespaceAscii(*(end - 1))) + { --end; + } } - } // namespace Str diff --git a/source/gui/resource.h b/source/gui/resource.h index 638f71a9..294051be 100644 --- a/source/gui/resource.h +++ b/source/gui/resource.h @@ -2,15 +2,15 @@ // Microsoft Developer Studio generated include file. // Used by icon.rc // -#define IDI_ICON1 101 +#define IDI_ICON1 101 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/source/gui/servergui.cpp b/source/gui/servergui.cpp index 6ffa7f7a..9e567043 100644 --- a/source/gui/servergui.cpp +++ b/source/gui/servergui.cpp @@ -48,46 +48,49 @@ #include "stop.xpm" #include "stop_dis.xpm" -class MyApp : public wxApp { +class MyApp : public wxApp +{ public: virtual bool OnInit(); virtual bool OnExceptionInMainLoop(); }; -typedef struct log_queue_element_t { - int level; +typedef struct log_queue_element_t +{ + int level; UTFString msg; UTFString msgf; } log_queue_element_t; // Define a new frame type: this is going to be our main frame -class MyDialog : public wxDialog { +class MyDialog : public wxDialog +{ public: // ctor(s) MyDialog(const wxString &title, MyApp *_app); - void logCallback(int level, UTFString msg, UTFString msgf); //called by callback function + void logCallback(int level, UTFString msg, UTFString msgf); //called by callback function private: - MyApp *app; - wxButton *startBtn, *stopBtn, *exitBtn, *pubipBtn; - wxTextCtrl *txtConsole, *ipaddr, *port, *slots, *passwd, *terrain, *sname, *logfilename, *adminuid; - wxComboBox *smode, *logmode; - wxNotebook *nbook; - wxListCtrl *slotlist; + MyApp *app; + wxButton *startBtn, *stopBtn, *exitBtn, *pubipBtn; + wxTextCtrl *txtConsole, *ipaddr, *port, *slots, *passwd, *terrain, *sname, *logfilename, *adminuid; + wxComboBox *smode, *logmode; + wxNotebook *nbook; + wxListCtrl *slotlist; wxScrolledWindow *settingsPanel; - wxPanel *logPanel, *playersPanel; - wxTimer *timer1; - wxToolBar *tb; + wxPanel *logPanel, *playersPanel; + wxTimer *timer1; + wxToolBar *tb; void OnQuit(wxCloseEvent &event); - int loglevel; - int secondsCounter; - pthread_t notifyThread; - bool server_is_running; + int loglevel; + int secondsCounter; + pthread_t notifyThread; + bool server_is_running; - Mutex log_queue_mutex; + Mutex log_queue_mutex; std::deque log_queue; void OnBtnStart(wxCommandEvent &event); @@ -113,59 +116,56 @@ class MyDialog : public wxDialog { DECLARE_EVENT_TABLE() }; -enum { +enum +{ btn_start, btn_stop, btn_exit, EVT_timer1, btn_pubip, ctxtmenu_kick, ctxtmenu_ban, ctxtmenu_pm }; -BEGIN_EVENT_TABLE(MyDialog, wxDialog -) +BEGIN_EVENT_TABLE(MyDialog, wxDialog) EVT_CLOSE(MyDialog::OnQuit) -EVT_BUTTON(btn_start, MyDialog::OnBtnStart -) -EVT_BUTTON(btn_stop, MyDialog::OnBtnStop -) -EVT_BUTTON(btn_exit, MyDialog::OnBtnExit -) -EVT_BUTTON(btn_pubip, MyDialog::OnBtnPubIP -) -EVT_TIMER(EVT_timer1, MyDialog::OnTimer -) - -EVT_TOOL(btn_start, MyDialog::OnBtnStart -) -EVT_TOOL(btn_stop, MyDialog::OnBtnStop -) -EVT_TOOL(btn_exit, MyDialog::OnBtnExit -) +EVT_BUTTON(btn_start, MyDialog::OnBtnStart) +EVT_BUTTON(btn_stop, MyDialog::OnBtnStop) +EVT_BUTTON(btn_exit, MyDialog::OnBtnExit) +EVT_BUTTON(btn_pubip, MyDialog::OnBtnPubIP) +EVT_TIMER(EVT_timer1, MyDialog::OnTimer) + +EVT_TOOL(btn_start, MyDialog::OnBtnStart) +EVT_TOOL(btn_stop, MyDialog::OnBtnStop) +EVT_TOOL(btn_exit, MyDialog::OnBtnExit) END_EVENT_TABLE() IMPLEMENT_APP(MyApp) -inline wxString conv(const char *s) { +inline wxString conv(const char *s) +{ return wxString(s, wxConvUTF8); } -inline wxString conv(const std::string &s) { +inline wxString conv(const std::string &s) +{ return wxString(s.c_str(), wxConvUTF8); } -inline std::string conv(const wxString &s) { +inline std::string conv(const wxString &s) +{ return std::string(s.mb_str(wxConvUTF8)); } -void *s_notifyThreadStart(void *vid) { +void *s_notifyThreadStart(void *vid) +{ STACKLOG; Sequencer::notifyRoutine(); return NULL; } MyDialog *dialogInstance = 0; // we need to use this to be able to forward the messages -MyApp *myApp = 0; +MyApp *myApp = 0; // 'Main program' equivalent: the program execution "starts" here -bool MyApp::OnInit() { +bool MyApp::OnInit() +{ if (!wxApp::OnInit()) return false; @@ -177,7 +177,8 @@ bool MyApp::OnInit() { return true; } -bool MyApp::OnExceptionInMainLoop() { +bool MyApp::OnExceptionInMainLoop() +{ // something went wrong :/ try { throw; @@ -194,31 +195,35 @@ bool MyApp::OnExceptionInMainLoop() { return false; } -void pureLogCallback(int level, UTFString msg, UTFString msgf) { +void pureLogCallback(int level, UTFString msg, UTFString msgf) +{ dialogInstance->logCallback(level, msg, msgf); } -void MyDialog::logCallback(int level, UTFString msg, UTFString msgf) { - if (level < loglevel) return; +void MyDialog::logCallback(int level, UTFString msg, UTFString msgf) +{ + if (level < loglevel) + return; pthread_mutex_lock(log_queue_mutex.getRaw()); if (log_queue.size() > 100) log_queue.pop_front(); log_queue_element_t h; h.level = level; - h.msg = msg; - h.msgf = msgf; + h.msg = msg; + h.msgf = msgf; log_queue.push_back(h); pthread_mutex_unlock(log_queue_mutex.getRaw()); } MyDialog::MyDialog(const wxString &title, MyApp *_app) : - wxDialog(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600, 600), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - app = _app; - loglevel = LOG_INFO; + wxDialog(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600, 600), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + app = _app; + loglevel = LOG_INFO; dialogInstance = this; - secondsCounter = 55; // trigger at start + secondsCounter = 55; // trigger at start SetMinSize(wxSize(600, 600)); //SetMaxSize(wxSize(500,500)); @@ -268,9 +273,9 @@ MyDialog::MyDialog(const wxString &title, MyApp *_app) : //settingsPanel->SetVirtualSize(300, 800); settingsPanel->SetScrollbars(0, 10, 1, 0, 0, 0); - wxSizer *settingsSizer = new wxBoxSizer(wxVERTICAL); - wxFlexGridSizer *grid_sizer = new wxFlexGridSizer(3, 2, 10, 20); - wxStaticText *dText; + wxSizer *settingsSizer = new wxBoxSizer(wxVERTICAL); + wxFlexGridSizer *grid_sizer = new wxFlexGridSizer(3, 2, 10, 20); + wxStaticText *dText; // server version dText = new wxStaticText(settingsPanel, wxID_ANY, _("Server Version:"), wxDefaultPosition, wxDefaultSize, @@ -295,8 +300,8 @@ MyDialog::MyDialog(const wxString &title, MyApp *_app) : wxString choices[2]; choices[0] = _("LAN"); choices[1] = _("Internet"); - smode = new wxComboBox(settingsPanel, wxID_ANY, _("LAN"), wxDefaultPosition, wxDefaultSize, 2, choices, - wxCB_DROPDOWN | wxCB_READONLY); + smode = new wxComboBox(settingsPanel, wxID_ANY, _("LAN"), wxDefaultPosition, wxDefaultSize, 2, choices, + wxCB_DROPDOWN | wxCB_READONLY); grid_sizer->Add(smode, 0, wxGROW); // IP @@ -343,8 +348,8 @@ MyDialog::MyDialog(const wxString &title, MyApp *_app) : choices_log[3] = _("INFO"); choices_log[4] = _("WARN"); choices_log[5] = _("ERRROR"); - logmode = new wxComboBox(settingsPanel, wxID_ANY, _("INFO"), wxDefaultPosition, wxDefaultSize, 6, choices_log, - wxCB_DROPDOWN | wxCB_READONLY); + logmode = new wxComboBox(settingsPanel, wxID_ANY, _("INFO"), wxDefaultPosition, wxDefaultSize, 6, choices_log, + wxCB_DROPDOWN | wxCB_READONLY); grid_sizer->Add(logmode, 0, wxGROW); // logfilename @@ -422,7 +427,8 @@ MyDialog::MyDialog(const wxString &title, MyApp *_app) : Centre(); } -void MyDialog::OnTimer(wxTimerEvent &event) { +void MyDialog::OnTimer(wxTimerEvent &event) +{ STACKLOG; // update the player tab // TODO: add a flag, so this is only updated when needed @@ -432,8 +438,10 @@ void MyDialog::OnTimer(wxTimerEvent &event) { updateLogTab(); secondsCounter++; - if (secondsCounter > 60) { - if (Config::getServerMode() == SERVER_LAN) { + if (secondsCounter > 60) + { + if (Config::getServerMode() == SERVER_LAN) + { Messaging::updateMinuteStats(); Sequencer::updateMinuteStats(); @@ -444,12 +452,15 @@ void MyDialog::OnTimer(wxTimerEvent &event) { } } -void MyDialog::updateLogTab() { - if (!log_queue.empty()) { +void MyDialog::updateLogTab() +{ + if (!log_queue.empty()) + { pthread_mutex_lock(log_queue_mutex.getRaw()); txtConsole->Freeze(); int lines = 0; - while (!log_queue.empty()) { + while (!log_queue.empty()) + { log_queue_element_t h = log_queue.front(); log_queue.pop_front(); @@ -468,8 +479,10 @@ void MyDialog::updateLogTab() { UTFString u = h.msgf; for (unsigned int i = 0; i < u.size(); i++) + { if (u[i] == '\n') ++lines; + } wxString wmsg = wxString(u.asWStr()); txtConsole->AppendText(wmsg); @@ -481,13 +494,16 @@ void MyDialog::updateLogTab() { } } -void MyDialog::updatePlayerList() { +void MyDialog::updatePlayerList() +{ slotlist->Freeze(); std::vector clients = Sequencer::getClients(); - for (unsigned int i = 0; i < Config::getMaxClients(); i++) { + for (unsigned int i = 0; i < Config::getMaxClients(); i++) + { slotlist->SetItem(i, 0, wxString::Format(wxT("%d"), i)); - if (i >= clients.size()) { + if (i >= clients.size()) + { if (slotlist->GetItemText(i, 1) == _("FREE")) break; slotlist->SetItem(i, 1, _("FREE")); @@ -510,11 +526,16 @@ void MyDialog::updatePlayerList() { slotlist->SetItem(i, 3, conv(clients[i].ip_addr)); char authst[5] = ""; - if (clients[i].user.authstatus & AUTH_ADMIN) strcat(authst, "A"); - if (clients[i].user.authstatus & AUTH_MOD) strcat(authst, "M"); - if (clients[i].user.authstatus & AUTH_RANKED) strcat(authst, "R"); - if (clients[i].user.authstatus & AUTH_BOT) strcat(authst, "B"); - if (clients[i].user.authstatus & AUTH_BANNED) strcat(authst, "X"); + if (clients[i].user.authstatus & AUTH_ADMIN) + strcat(authst, "A"); + if (clients[i].user.authstatus & AUTH_MOD) + strcat(authst, "M"); + if (clients[i].user.authstatus & AUTH_RANKED) + strcat(authst, "R"); + if (clients[i].user.authstatus & AUTH_BOT) + strcat(authst, "B"); + if (clients[i].user.authstatus & AUTH_BANNED) + strcat(authst, "X"); slotlist->SetItem(i, 4, conv(authst)); wxString un = wxString(tryConvertUTF(clients[i].user.username).asWStr()); slotlist->SetItem(i, 5, un); @@ -522,20 +543,23 @@ void MyDialog::updatePlayerList() { slotlist->Thaw(); } -void MyDialog::OnQuit(wxCloseEvent &event) { +void MyDialog::OnQuit(wxCloseEvent &event) +{ Destroy(); exit(0); } -void MyDialog::OnContextMenu(wxContextMenuEvent &event) { - if (server_is_running) { +void MyDialog::OnContextMenu(wxContextMenuEvent &event) +{ + if (server_is_running) + { // which client row is selected? long item = slotlist->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if (item == -1) return; // get the uid of that row - int uid = wxAtoi(slotlist->GetItemText(item, 2)); + int uid = wxAtoi(slotlist->GetItemText(item, 2)); wxString username = slotlist->GetItemText(item, 5); if (uid <= 0) @@ -544,7 +568,7 @@ void MyDialog::OnContextMenu(wxContextMenuEvent &event) { // build the menu wxPoint point = event.GetPosition(); point = ScreenToClient(point); - wxMenu menu; + wxMenu menu; menu.SetTitle(username); menu.Append(ctxtmenu_kick, wxT("&kick")); menu.Append(ctxtmenu_ban, wxT("&ban")); @@ -555,20 +579,24 @@ void MyDialog::OnContextMenu(wxContextMenuEvent &event) { const int rc = GetPopupMenuSelectionFromUser(menu, point); // interpret the selection and take the required action - if (rc == ctxtmenu_kick) { + if (rc == ctxtmenu_kick) + { wxString msg; msg.sprintf("Are you sure that you wish to kick user '%s'?", username); - int answer = wxMessageBox(msg, _("Confirmation required"), wxYES_NO | wxCANCEL, dialogInstance); + int answer = wxMessageBox(msg, _("Confirmation required"), wxYES_NO | wxCANCEL, dialogInstance); if (answer == wxYES) Sequencer::disconnect(uid, "Kicked by host.", false); - } else if (rc == ctxtmenu_ban) { + } + else if (rc == ctxtmenu_ban) + { wxString msg; msg.sprintf("Are you sure that you wish to kick and ban user '%s'?", username); - int answer = wxMessageBox(msg, _("Confirmation required"), wxYES_NO | wxCANCEL, dialogInstance); - if (answer == wxYES) { + int answer = wxMessageBox(msg, _("Confirmation required"), wxYES_NO | wxCANCEL, dialogInstance); + if (answer == wxYES) Sequencer::silentBan(uid, "Banned by host."); - } - } else if (rc == ctxtmenu_pm) { + } + else if (rc == ctxtmenu_pm) + { wxString msg; msg = wxGetTextFromUser(_("Please enter your private message:"), _("Private message"), @@ -577,7 +605,7 @@ void MyDialog::OnContextMenu(wxContextMenuEvent &event) { wxDefaultCoord, wxDefaultCoord, true - ); + ); if (!msg.IsEmpty()) Sequencer::serverSay(std::string(msg.mb_str()), uid, FROM_HOST); } @@ -585,7 +613,8 @@ void MyDialog::OnContextMenu(wxContextMenuEvent &event) { } -void MyDialog::OnBtnStart(wxCommandEvent &event) { +void MyDialog::OnBtnStart(wxCommandEvent &event) +{ tb->EnableTool(btn_start, false); settingsPanel->Disable(); wxBeginBusyCursor(); @@ -593,12 +622,16 @@ void MyDialog::OnBtnStart(wxCommandEvent &event) { //startBtn->Disable(); //stopBtn->Enable(); nbook->SetSelection(1); - if (startServer()) { + if (startServer()) + { settingsPanel->Enable(); tb->EnableTool(btn_start, true); - } else { + } + else + { // build the playerlist - for (unsigned int i = 0; i < Config::getMaxClients(); i++) { + for (unsigned int i = 0; i < Config::getMaxClients(); i++) + { slotlist->InsertItem(i, wxString::Format(wxT("%d"), i)); slotlist->SetItem(i, 1, _("FREE")); } @@ -611,7 +644,8 @@ void MyDialog::OnBtnStart(wxCommandEvent &event) { wxEndBusyCursor(); } -void MyDialog::OnBtnStop(wxCommandEvent &event) { +void MyDialog::OnBtnStop(wxCommandEvent &event) +{ tb->EnableTool(btn_stop, false); wxBeginBusyCursor(); @@ -632,25 +666,35 @@ void MyDialog::OnBtnStop(wxCommandEvent &event) { wxEndBusyCursor(); } -void MyDialog::OnBtnExit(wxCommandEvent &event) { +void MyDialog::OnBtnExit(wxCommandEvent &event) +{ Destroy(); exit(0); } -void MyDialog::OnBtnPubIP(wxCommandEvent &event) { +void MyDialog::OnBtnPubIP(wxCommandEvent &event) +{ wxString ip = conv(Config::getPublicIP()); + ipaddr->SetValue(ip); } -int MyDialog::startServer() { +int MyDialog::startServer() +{ // set default verbose levels loglevel = LOG_INFO; - if (logmode->GetValue() == _("STACK")) loglevel = LOG_STACK; - if (logmode->GetValue() == _("DEBUG")) loglevel = LOG_DEBUG; - if (logmode->GetValue() == _("VERBOSE")) loglevel = LOG_VERBOSE; - if (logmode->GetValue() == _("INFO")) loglevel = LOG_INFO; - if (logmode->GetValue() == _("WARN")) loglevel = LOG_WARN; - if (logmode->GetValue() == _("ERROR")) loglevel = LOG_ERROR; + if (logmode->GetValue() == _("STACK")) + loglevel = LOG_STACK; + if (logmode->GetValue() == _("DEBUG")) + loglevel = LOG_DEBUG; + if (logmode->GetValue() == _("VERBOSE")) + loglevel = LOG_VERBOSE; + if (logmode->GetValue() == _("INFO")) + loglevel = LOG_INFO; + if (logmode->GetValue() == _("WARN")) + loglevel = LOG_WARN; + if (logmode->GetValue() == _("ERROR")) + loglevel = LOG_ERROR; Logger::setLogLevel(LOGTYPE_FILE, LOG_VERBOSE); Logger::setOutputFile("server.log"); @@ -689,26 +733,29 @@ int MyDialog::startServer() { Config::setPublicPass(conv(passwd->GetValue())); //server name, replace space with underscore - wxString server_name = sname->GetValue(); - const wxString from = wxString(" "); - const wxString to = wxString("%20"); + wxString server_name = sname->GetValue(); + const wxString from = wxString(" "); + const wxString to = wxString("%20"); server_name.Replace(from, to, true); - if (!Config::setServerName(conv(server_name))) { + if (!Config::setServerName(conv(server_name))) + { Logger::log(LOG_ERROR, "Invalid servername!"); wxBell(); return 1; } // set the terrain - if (!Config::setTerrain(conv(terrain->GetValue()))) { + if (!Config::setTerrain(conv(terrain->GetValue()))) + { Logger::log(LOG_ERROR, "Invalid terrain name!"); wxBell(); return 1; } // check the configuration - if (!Config::checkConfig()) { + if (!Config::checkConfig()) + { wxBell(); return 1; } @@ -717,7 +764,8 @@ int MyDialog::startServer() { Sequencer::initilize(); // set the admin - if (!adminuid->GetValue().IsEmpty()) { + if (!adminuid->GetValue().IsEmpty()) + { std::string user_token = conv(adminuid->GetValue()); SHA1FromString(user_token, user_token); if (Sequencer::getUserAuth()) @@ -734,12 +782,14 @@ int MyDialog::startServer() { return 0; } -int MyDialog::stopServer() { +int MyDialog::stopServer() +{ server_is_running = false; - if (Sequencer::getNotifier()) { + if (Sequencer::getNotifier()) + { pthread_cancel(notifyThread); pthread_detach(notifyThread); } Sequencer::cleanUp(); return 0; -} \ No newline at end of file +} diff --git a/source/gui/statpict.cpp b/source/gui/statpict.cpp index 5a9f1975..d5746cee 100644 --- a/source/gui/statpict.cpp +++ b/source/gui/statpict.cpp @@ -19,18 +19,15 @@ #include "statpict.h" #include "wx/dcclient.h" -IMPLEMENT_DYNAMIC_CLASS(wxStaticPicture, wxControl -) -const wxChar *wxStaticPictureNameStr = wxT("staticPicture"); +IMPLEMENT_DYNAMIC_CLASS(wxStaticPicture, wxControl) +const wxChar * wxStaticPictureNameStr = wxT("staticPicture"); /* * wxStaticPicture */ -BEGIN_EVENT_TABLE(wxStaticPicture, wxControl -) +BEGIN_EVENT_TABLE(wxStaticPicture, wxControl) EVT_PAINT(wxStaticPicture::OnPaint) - END_EVENT_TABLE() bool wxStaticPicture::Create(wxWindow *parent, wxWindowID id, @@ -38,11 +35,13 @@ bool wxStaticPicture::Create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &s, long style, - const wxString &name) { + const wxString &name) +{ SetName(name); wxSize size = s; - if (bitmap.Ok()) { + if (bitmap.Ok()) + { if (size.x == wxDefaultCoord) size.x = bitmap.GetWidth(); if (size.y == wxDefaultCoord) @@ -53,8 +52,8 @@ bool wxStaticPicture::Create(wxWindow *parent, wxWindowID id, m_foregroundColour = parent->GetForegroundColour(); Bitmap = bitmap; - Align = 0; - Scale = 0; + Align = 0; + Scale = 0; ScaleX = ScaleY = 1; #ifndef __WXMSW__ @@ -64,7 +63,7 @@ bool wxStaticPicture::Create(wxWindow *parent, wxWindowID id, #endif if (id == wxID_ANY) - m_windowId = (int) NewControlId(); + m_windowId = (int)NewControlId(); else m_windowId = id; @@ -77,7 +76,8 @@ bool wxStaticPicture::Create(wxWindow *parent, wxWindowID id, return ret; } -void wxStaticPicture::SetBitmap(const wxBitmap &bmp) { +void wxStaticPicture::SetBitmap(const wxBitmap &bmp) +{ Bitmap = bmp; #ifndef __WXMSW__ if (Bitmap.Ok()) @@ -86,7 +86,8 @@ void wxStaticPicture::SetBitmap(const wxBitmap &bmp) { #endif } -void wxStaticPicture::OnPaint(wxPaintEvent &WXUNUSED(event)) { +void wxStaticPicture::OnPaint(wxPaintEvent &WXUNUSED(event)) +{ if (!Bitmap.Ok()) return; @@ -96,50 +97,62 @@ void wxStaticPicture::OnPaint(wxPaintEvent &WXUNUSED(event)) { wxSize sz = GetSize(); wxSize bmpsz(Bitmap.GetWidth(), Bitmap.GetHeight()); - float sx = 1.0f, sy = 1.0f; + float sx = 1.0f, sy = 1.0f; - if (Scale & wxSCALE_UNIFORM) { - float _sx = (float) sz.GetWidth() / (float) bmpsz.GetWidth(); - float _sy = (float) sz.GetHeight() / (float) bmpsz.GetHeight(); + if (Scale & wxSCALE_UNIFORM) + { + float _sx = (float)sz.GetWidth() / (float)bmpsz.GetWidth(); + float _sy = (float)sz.GetHeight() / (float)bmpsz.GetHeight(); sx = sy = _sx < _sy ? _sx : _sy; - } else if (Scale & wxSCALE_CUSTOM) { + } + else if (Scale & wxSCALE_CUSTOM) + { sx = ScaleX; sy = ScaleY; - } else { + } + else + { if (Scale & wxSCALE_HORIZONTAL) - sx = (float) sz.x / (float) bmpsz.x; + sx = (float)sz.x / (float)bmpsz.x; if (Scale & wxSCALE_VERTICAL) - sy = (float) sz.y / (float) bmpsz.y; + sy = (float)sz.y / (float)bmpsz.y; } - bmpsz = wxSize((int) (bmpsz.x * sx), (int) (bmpsz.y * sy)); + bmpsz = wxSize((int)(bmpsz.x * sx), (int)(bmpsz.y * sy)); wxPoint pos(0, 0); - if (Align & wxALIGN_CENTER_HORIZONTAL) pos.x = (sz.x - bmpsz.x) / 2; - else if (Align & wxALIGN_RIGHT) pos.x = sz.x - bmpsz.x; + if (Align & wxALIGN_CENTER_HORIZONTAL) + pos.x = (sz.x - bmpsz.x) / 2; + else if (Align & wxALIGN_RIGHT) + pos.x = sz.x - bmpsz.x; - if (Align & wxALIGN_CENTER_VERTICAL) pos.y = (sz.y - bmpsz.y) / 2; - else if (Align & wxALIGN_BOTTOM) pos.y = sz.y - bmpsz.y; + if (Align & wxALIGN_CENTER_VERTICAL) + pos.y = (sz.y - bmpsz.y) / 2; + else if (Align & wxALIGN_BOTTOM) + pos.y = sz.y - bmpsz.y; - if (Scale) { + if (Scale) + { #ifdef __WXMSW__ double ux, uy; - dc.GetUserScale( &ux, &uy ); - dc.SetUserScale( ux*sx, uy*sy ); - dc.DrawBitmap( Bitmap, (int)((float)pos.x/sx), (int)((float)pos.y/sy) ); - dc.SetUserScale( ux, uy ); + dc.GetUserScale(&ux, &uy); + dc.SetUserScale(ux * sx, uy * sy); + dc.DrawBitmap(Bitmap, (int)((float)pos.x / sx), (int)((float)pos.y / sy)); + dc.SetUserScale(ux, uy); #else - if (LastScaleX != sx || LastScaleY != sy) { - LastScaleX = sx; - LastScaleY = sy; + if (LastScaleX != sx || LastScaleY != sy) + { + LastScaleX = sx; + LastScaleY = sy; ScaledBitmap = wxBitmap(OriginalImage.Scale(bmpsz.x, bmpsz.y)); } dc.DrawBitmap(ScaledBitmap, pos.x, pos.y); #endif - } else + } + else + { dc.DrawBitmap(Bitmap, pos.x, pos.y); - -// dc.EndDrawing(); + // dc.EndDrawing(); + } } - diff --git a/source/gui/statpict.h b/source/gui/statpict.h index 29bda235..7cd869ac 100644 --- a/source/gui/statpict.h +++ b/source/gui/statpict.h @@ -24,27 +24,32 @@ //#include "wx/gizmos/gizmos.h" -enum { +enum +{ wxSCALE_HORIZONTAL = 0x1, - wxSCALE_VERTICAL = 0x2, - wxSCALE_UNIFORM = 0x4, - wxSCALE_CUSTOM = 0x8 + wxSCALE_VERTICAL = 0x2, + wxSCALE_UNIFORM = 0x4, + wxSCALE_CUSTOM = 0x8 }; extern const wxChar *wxStaticPictureNameStr; -class wxStaticPicture : public wxControl { +class wxStaticPicture : public wxControl +{ DECLARE_DYNAMIC_CLASS(wxStaticPicture) public: - wxStaticPicture() {} + wxStaticPicture() + { + } wxStaticPicture(wxWindow *parent, wxWindowID id, const wxBitmap &label, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0, - const wxString &name = wxStaticPictureNameStr) { + const wxString &name = wxStaticPictureNameStr) + { Create(parent, id, label, pos, size, style, name); } @@ -55,60 +60,77 @@ class wxStaticPicture : public wxControl { long style = 0, const wxString &name = wxStaticPictureNameStr); - virtual void Command(wxCommandEvent &WXUNUSED(event)) {} + virtual void Command(wxCommandEvent &WXUNUSED(event)) + { + } - virtual bool ProcessCommand(wxCommandEvent &WXUNUSED(event)) { return true; } + virtual bool ProcessCommand(wxCommandEvent &WXUNUSED(event)) + { + return true; + } void OnPaint(wxPaintEvent &event); void SetBitmap(const wxBitmap &bmp); - wxBitmap GetBitmap() const { + wxBitmap GetBitmap() const + { return Bitmap; } // Icon interface for compatibility with wxStaticBitmap. - void SetIcon(const wxIcon &icon) { + void SetIcon(const wxIcon &icon) + { wxBitmap bmp; + bmp.CopyFromIcon(icon); SetBitmap(bmp); } - wxSize DoGetBestSize() const { + wxSize DoGetBestSize() const + { if (!Bitmap.Ok()) return wxSize(100, 100); else return wxSize(Bitmap.GetWidth(), Bitmap.GetHeight()); } - wxIcon GetIcon() const { + wxIcon GetIcon() const + { wxIcon icon; + icon.CopyFromBitmap(Bitmap); return icon; } - void SetAlignment(int align) { + void SetAlignment(int align) + { Align = align; } - int GetAlignment() const { + int GetAlignment() const + { return Align; } - void SetScale(int scale) { + void SetScale(int scale) + { Scale = scale; } - int GetScale() const { + int GetScale() const + { return Scale; } - void SetCustomScale(float sx, float sy) { + void SetCustomScale(float sx, float sy) + { ScaleX = sx; ScaleY = sy; } - void GetCustomScale(float *sx, float *sy) const { + void GetCustomScale(float *sx, float *sy) const + { *sx = ScaleX; *sy = ScaleY; } @@ -116,20 +138,20 @@ class wxStaticPicture : public wxControl { protected: wxBitmap Bitmap; - int Align; + int Align; - int Scale; - float ScaleX; - float ScaleY; + int Scale; + float ScaleX; + float ScaleY; #ifndef __WXMSW__ // When scaling is enabled, measures are taken to improve performance on non-Windows platforms. // - The original bitmap is stored as a wxImage, because conversion from wxBitmap to wxImage is slow. // - The latest scaled bitmap is cached, this improves performance when the control is repainted // but the size hasn't changed (overlapping windows, movement, etc). - wxImage OriginalImage; - float LastScaleX; - float LastScaleY; + wxImage OriginalImage; + float LastScaleX; + float LastScaleY; wxBitmap ScaledBitmap; #endif diff --git a/source/protocol/rornet.h b/source/protocol/rornet.h index 6bed6285..2b594fcb 100644 --- a/source/protocol/rornet.h +++ b/source/protocol/rornet.h @@ -1,187 +1,192 @@ /* - This file is part of Rigs of Rods - - Copyright 2007 Pierre-Michel Ricordel - Copyright 2014+ Petr Ohlidal & contributors. - - Rigs of Rods is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 3 of the License. - - Rigs of Rods is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ + * This file is part of Rigs of Rods + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Petr Ohlidal & contributors. + * + * Rigs of Rods is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3 of the License. + * + * Rigs of Rods is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #pragma once #include -#define BITMASK(x) (1 << (x-1)) +#define BITMASK(x) (1 << (x - 1)) #ifdef _MSC_VER // MSVC: set global packing and make PACKED an empty macro # pragma pack(push, 1) # define PACKED #else // GCC/Clang: use standard attribute -# define PACKED __attribute__((packed)) +# define PACKED __attribute__((packed)) #endif -namespace RoRnet { - -#define RORNET_MAX_PEERS 64 //!< maximum clients connected at the same time -#define RORNET_MAX_MESSAGE_LENGTH 16384 //!< maximum size of a RoR message. 32768 bytes = 8 kilobytes -#define RORNET_LAN_BROADCAST_PORT 13000 //!< port used to send the broadcast announcement in LAN mode -#define RORNET_MAX_USERNAME_LEN 40 //!< port used to send the broadcast announcement in LAN mode +namespace RoRnet +{ +#define RORNET_MAX_PEERS 64 //!< maximum clients connected at the same time +#define RORNET_MAX_MESSAGE_LENGTH 16384 //!< maximum size of a RoR message. 32768 bytes = 8 kilobytes +#define RORNET_LAN_BROADCAST_PORT 13000 //!< port used to send the broadcast announcement in LAN mode +#define RORNET_MAX_USERNAME_LEN 40 //!< port used to send the broadcast announcement in LAN mode -#define RORNET_VERSION "RoRnet_2.40" +#define RORNET_VERSION "RoRnet_2.40" - enum MessageType { - MSG2_HELLO = 1025, //!< client sends its version as first message + enum MessageType + { + MSG2_HELLO = 1025, //!< client sends its version as first message // Hello responses - MSG2_FULL, //!< no more slots for us - MSG2_WRONG_PW, //!< server send that on wrong pw - MSG2_WRONG_VER, //!< wrong version - MSG2_BANNED, //!< client not allowed to join - MSG2_WELCOME, //!< we can proceed + MSG2_FULL, //!< no more slots for us + MSG2_WRONG_PW, //!< server send that on wrong pw + MSG2_WRONG_VER, //!< wrong version + MSG2_BANNED, //!< client not allowed to join + MSG2_WELCOME, //!< we can proceed // Technical - MSG2_VERSION, //!< server responds with its version - MSG2_SERVER_SETTINGS, //!< server send client the terrain name: server_info_t - MSG2_USER_INFO, //!< user data that is sent from the server to the clients - MSG2_MASTERINFO, //!< master information response - MSG2_NETQUALITY, //!< network quality information + MSG2_VERSION, //!< server responds with its version + MSG2_SERVER_SETTINGS, //!< server send client the terrain name: server_info_t + MSG2_USER_INFO, //!< user data that is sent from the server to the clients + MSG2_MASTERINFO, //!< master information response + MSG2_NETQUALITY, //!< network quality information // Gameplay - MSG2_GAME_CMD, //!< Script message. Can be sent in both directions. - MSG2_USER_JOIN, //!< new user joined - MSG2_USER_LEAVE, //!< user leaves - MSG2_UTF8_CHAT, //!< chat line in UTF8 encoding - MSG2_UTF8_PRIVCHAT, //!< private chat line in UTF8 encoding + MSG2_GAME_CMD, //!< Script message. Can be sent in both directions. + MSG2_USER_JOIN, //!< new user joined + MSG2_USER_LEAVE, //!< user leaves + MSG2_UTF8_CHAT, //!< chat line in UTF8 encoding + MSG2_UTF8_PRIVCHAT, //!< private chat line in UTF8 encoding // Stream functions - MSG2_STREAM_REGISTER, //!< create new stream - MSG2_STREAM_REGISTER_RESULT, //!< result of a stream creation - MSG2_STREAM_UNREGISTER, //!< remove stream - MSG2_STREAM_DATA, //!< stream data + MSG2_STREAM_REGISTER, //!< create new stream + MSG2_STREAM_REGISTER_RESULT, //!< result of a stream creation + MSG2_STREAM_UNREGISTER, //!< remove stream + MSG2_STREAM_DATA, //!< stream data }; - enum UserAuth { - AUTH_NONE = 0, //!< no authentication - AUTH_ADMIN = BITMASK(1), //!< admin on the server - AUTH_RANKED = BITMASK(2), //!< ranked status - AUTH_MOD = BITMASK(3), //!< moderator status - AUTH_BOT = BITMASK(4), //!< bot status - AUTH_BANNED = BITMASK(5) //!< banned + enum UserAuth + { + AUTH_NONE = 0, //!< no authentication + AUTH_ADMIN = BITMASK(1), //!< admin on the server + AUTH_RANKED = BITMASK(2), //!< ranked status + AUTH_MOD = BITMASK(3), //!< moderator status + AUTH_BOT = BITMASK(4), //!< bot status + AUTH_BANNED = BITMASK(5) //!< banned }; - enum Netmask { - NETMASK_HORN = BITMASK(1), //!< horn is in use - NETMASK_LIGHTS = BITMASK(2), //!< lights on - NETMASK_BRAKES = BITMASK(3), //!< brake lights on - NETMASK_REVERSE = BITMASK(4), //!< reverse light on - NETMASK_BEACONS = BITMASK(5), //!< beacons on - NETMASK_BLINK_LEFT = BITMASK(6), //!< left blinker on - NETMASK_BLINK_RIGHT = BITMASK(7), //!< right blinker on - NETMASK_BLINK_WARN = BITMASK(8), //!< warn blinker on - NETMASK_CLIGHT1 = BITMASK(9), //!< custom light 1 on - NETMASK_CLIGHT2 = BITMASK(10), //!< custom light 2 on - NETMASK_CLIGHT3 = BITMASK(11), //!< custom light 3 on - NETMASK_CLIGHT4 = BITMASK(12), //!< custom light 4 on - NETMASK_POLICEAUDIO = BITMASK(13), //!< police siren on - NETMASK_PARTICLE = BITMASK(14), //!< custom particles on - NETMASK_PBRAKE = BITMASK(15), //!< custom particles on - NETMASK_TC_ACTIVE = BITMASK(16), //!< traction control light on? - NETMASK_ALB_ACTIVE = BITMASK(17), //!< anti lock brake light on? - NETMASK_ENGINE_CONT = BITMASK(18), //!< ignition on? - NETMASK_ENGINE_RUN = BITMASK(19), //!< engine running? - - NETMASK_ENGINE_MODE_AUTOMATIC = BITMASK(20), //!< engine mode - NETMASK_ENGINE_MODE_SEMIAUTO = BITMASK(21), //!< engine mode - NETMASK_ENGINE_MODE_MANUAL = BITMASK(22), //!< engine mode - NETMASK_ENGINE_MODE_MANUAL_STICK = BITMASK(23), //!< engine mode + enum Netmask + { + NETMASK_HORN = BITMASK(1), //!< horn is in use + NETMASK_LIGHTS = BITMASK(2), //!< lights on + NETMASK_BRAKES = BITMASK(3), //!< brake lights on + NETMASK_REVERSE = BITMASK(4), //!< reverse light on + NETMASK_BEACONS = BITMASK(5), //!< beacons on + NETMASK_BLINK_LEFT = BITMASK(6), //!< left blinker on + NETMASK_BLINK_RIGHT = BITMASK(7), //!< right blinker on + NETMASK_BLINK_WARN = BITMASK(8), //!< warn blinker on + NETMASK_CLIGHT1 = BITMASK(9), //!< custom light 1 on + NETMASK_CLIGHT2 = BITMASK(10), //!< custom light 2 on + NETMASK_CLIGHT3 = BITMASK(11), //!< custom light 3 on + NETMASK_CLIGHT4 = BITMASK(12), //!< custom light 4 on + NETMASK_POLICEAUDIO = BITMASK(13), //!< police siren on + NETMASK_PARTICLE = BITMASK(14), //!< custom particles on + NETMASK_PBRAKE = BITMASK(15), //!< custom particles on + NETMASK_TC_ACTIVE = BITMASK(16), //!< traction control light on? + NETMASK_ALB_ACTIVE = BITMASK(17), //!< anti lock brake light on? + NETMASK_ENGINE_CONT = BITMASK(18), //!< ignition on? + NETMASK_ENGINE_RUN = BITMASK(19), //!< engine running? + + NETMASK_ENGINE_MODE_AUTOMATIC = BITMASK(20), //!< engine mode + NETMASK_ENGINE_MODE_SEMIAUTO = BITMASK(21), //!< engine mode + NETMASK_ENGINE_MODE_MANUAL = BITMASK(22), //!< engine mode + NETMASK_ENGINE_MODE_MANUAL_STICK = BITMASK(23), //!< engine mode NETMASK_ENGINE_MODE_MANUAL_RANGES = BITMASK(24) //!< engine mode }; -// -------------------------------- structs ----------------------------------- -// Only use datatypes with defined binary sizes (avoid bool, int, wchar_t...) -// Prefer alignment to 4 or 2 bytes (put int32/float/etc. fields on top) + // -------------------------------- structs ----------------------------------- + // Only use datatypes with defined binary sizes (avoid bool, int, wchar_t...) + // Prefer alignment to 4 or 2 bytes (put int32/float/etc. fields on top) - PACKED struct Header //!< Common header for every packet + PACKED struct Header //!< Common header for every packet { - uint32_t command; //!< the command of this packet: MSG2_* - int32_t source; //!< source of this command: 0 = server - uint32_t streamid; //!< streamid for this command - uint32_t size; //!< size of the attached data block + uint32_t command; //!< the command of this packet: MSG2_* + int32_t source; //!< source of this command: 0 = server + uint32_t streamid; //!< streamid for this command + uint32_t size; //!< size of the attached data block }; - PACKED struct StreamRegister //!< Sent from the client to server and vice versa, to broadcast a new stream + PACKED struct StreamRegister //!< Sent from the client to server and vice versa, to broadcast a new stream { - int32_t type; //!< stream type - int32_t status; //!< initial stream status - int32_t origin_sourceid; //!< origin sourceid - int32_t origin_streamid; //!< origin streamid - char name[128]; //!< the truck filename - char data[8000]; //!< data used for stream setup + int32_t type; //!< stream type + int32_t status; //!< initial stream status + int32_t origin_sourceid; //!< origin sourceid + int32_t origin_streamid; //!< origin streamid + char name[128]; //!< the truck filename + char data[8000]; //!< data used for stream setup }; - PACKED struct TruckStreamRegister { - int32_t type; //!< stream type - int32_t status; //!< initial stream status - int32_t origin_sourceid; //!< origin sourceid - int32_t origin_streamid; //!< origin streamid - int32_t bufferSize; //!< initial stream status - char name[128]; //!< the truck filename - char truckconfig[10][60]; //!< truck section configuration + PACKED struct TruckStreamRegister + { + int32_t type; //!< stream type + int32_t status; //!< initial stream status + int32_t origin_sourceid; //!< origin sourceid + int32_t origin_streamid; //!< origin streamid + int32_t bufferSize; //!< initial stream status + char name[128]; //!< the truck filename + char truckconfig[10][60]; //!< truck section configuration }; - PACKED struct StreamUnRegister //< sent to remove a stream + PACKED struct StreamUnRegister //< sent to remove a stream { uint32_t streamid; }; - PACKED struct UserInfo { - uint32_t uniqueid; //!< user unique id - int32_t authstatus; //!< auth status set by server: AUTH_* - int32_t slotnum; //!< slot number set by server - int32_t colournum; //!< colour set by server - - char username[RORNET_MAX_USERNAME_LEN]; //!< the nickname of the user - char usertoken[40]; //!< user token - char serverpassword[40]; //!< server password - char language[10]; //!< user's language. For example "de-DE" or "en-US" - char clientname[10]; //!< the name and version of the client. For exmaple: "ror" or "gamebot" - char clientversion[25]; //!< a version number of the client. For example 1 for RoR 0.35 - char clientGUID[40]; //!< the clients GUID - char sessiontype[10]; //!< the requested session type. For example "normal", "bot", "rcon" - char sessionoptions[128]; //!< reserved for future options + PACKED struct UserInfo + { + uint32_t uniqueid; //!< user unique id + int32_t authstatus; //!< auth status set by server: AUTH_* + int32_t slotnum; //!< slot number set by server + int32_t colournum; //!< colour set by server + + char username[RORNET_MAX_USERNAME_LEN]; //!< the nickname of the user + char usertoken[40]; //!< user token + char serverpassword[40]; //!< server password + char language[10]; //!< user's language. For example "de-DE" or "en-US" + char clientname[10]; //!< the name and version of the client. For exmaple: "ror" or "gamebot" + char clientversion[25]; //!< a version number of the client. For example 1 for RoR 0.35 + char clientGUID[40]; //!< the clients GUID + char sessiontype[10]; //!< the requested session type. For example "normal", "bot", "rcon" + char sessionoptions[128]; //!< reserved for future options }; - PACKED struct TruckState //!< Formerly `oob_t` + PACKED struct TruckState //!< Formerly `oob_t` { - int32_t time; //!< time data - float engine_speed; //!< engine RPM - float engine_force; //!< engine acceleration - float engine_clutch; //!< the clutch value - int32_t engine_gear; //!< engine gear - float hydrodirstate; //!< the turning direction status - float brake; //!< the brake value - float wheelspeed; //!< the wheel speed value - uint32_t flagmask; //!< flagmask: NETMASK_* + int32_t time; //!< time data + float engine_speed; //!< engine RPM + float engine_force; //!< engine acceleration + float engine_clutch; //!< the clutch value + int32_t engine_gear; //!< engine gear + float hydrodirstate; //!< the turning direction status + float brake; //!< the brake value + float wheelspeed; //!< the wheel speed value + uint32_t flagmask; //!< flagmask: NETMASK_* }; - PACKED struct ServerInfo { - char protocolversion[20]; //!< protocol version being used - char terrain[128]; //!< terrain name - char servername[128]; //!< name of the server - uint8_t has_password; //!< passworded server? - char info[4096]; //!< info text + PACKED struct ServerInfo + { + char protocolversion[20]; //!< protocol version being used + char terrain[128]; //!< terrain name + char servername[128]; //!< name of the server + uint8_t has_password; //!< passworded server? + char info[4096]; //!< info text }; - } // namespace RoRnet #ifdef _MSC_VER diff --git a/source/server/ScriptEngine.cpp b/source/server/ScriptEngine.cpp index bc891fd9..11c5b55b 100644 --- a/source/server/ScriptEngine.cpp +++ b/source/server/ScriptEngine.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2009 Thomas Fischer -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2009 Thomas Fischer + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ // created on 22th of June 2009 by Thomas Fischer #ifdef WITH_ANGELSCRIPT @@ -27,14 +27,14 @@ along with Foobar. If not, see . #include "sequencer.h" #include "config.h" #include "messaging.h" -#include "scriptstdstring/scriptstdstring.h" // angelscript addon -#include "scriptmath/scriptmath.h" // angelscript addon -#include "scriptmath3d/scriptmath3d.h" // angelscript addon -#include "scriptarray/scriptarray.h" // angelscript addon +#include "scriptstdstring/scriptstdstring.h" // angelscript addon +#include "scriptmath/scriptmath.h" // angelscript addon +#include "scriptmath3d/scriptmath3d.h" // angelscript addon +#include "scriptarray/scriptarray.h" // angelscript addon #include "scriptdictionary/scriptdictionary.h" // angelscript addon -#include "scriptany/scriptany.h" // angelscript addon -#include "scriptbuilder/scriptbuilder.h" // angelscript addon -#include "ScriptFileSafe.h" // (edited) angelscript addon +#include "scriptany/scriptany.h" // angelscript addon +#include "scriptbuilder/scriptbuilder.h" // angelscript addon +#include "ScriptFileSafe.h" // (edited) angelscript addon #include "utils.h" #include "SocketW.h" @@ -51,12 +51,12 @@ using namespace std; extern "C" { _CRTIMP void __cdecl _wassert(_In_z_ const wchar_t * _Message, _In_z_ const wchar_t *_File, _In_ unsigned _Line); } -# define assert_net(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) ) +# define assert_net(_Expression) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(# _Expression), _CRT_WIDE(__FILE__), __LINE__), 0)) #else // _WIN32 #include -# define assert_net(expr) assert(expr) +# define assert_net(expr) assert(expr) #endif // _WIN32 @@ -68,12 +68,14 @@ _CRTIMP void __cdecl _wassert(_In_z_ const wchar_t * _Message, _In_z_ const wcha // Stream_register_t wrapper -std::string stream_register_get_name(RoRnet::StreamRegister *reg) { +std::string stream_register_get_name(RoRnet::StreamRegister *reg) +{ return std::string(reg->name); } -void *s_sethreadstart(void *se) { - ((ScriptEngine *) se)->timerLoop(); +void *s_sethreadstart(void *se) +{ + ((ScriptEngine*)se)->timerLoop(); return NULL; } @@ -81,27 +83,34 @@ ScriptEngine::ScriptEngine(Sequencer *seq) : seq(seq), engine(0), context(0), frameStepThreadRunning(false), - exit(false) { + exit(false) +{ init(); } -ScriptEngine::~ScriptEngine() { +ScriptEngine::~ScriptEngine() +{ // Clean up exit = true; deleteAllCallbacks(); - if (engine) engine->Release(); - if (context) context->Release(); - if (frameStepThreadRunning) { + if (engine) + engine->Release(); + if (context) + context->Release(); + if (frameStepThreadRunning) pthread_join(timer_thread, NULL); - } } -void ScriptEngine::deleteAllCallbacks() { - if (!engine) return; +void ScriptEngine::deleteAllCallbacks() +{ + if (!engine) + return; for (std::map::iterator typeit = callbacks.begin(); - typeit != callbacks.end(); ++typeit) { - for (callbackList::iterator it = typeit->second.begin(); it != typeit->second.end(); ++it) { + typeit != callbacks.end(); ++typeit) + { + for (callbackList::iterator it = typeit->second.begin(); it != typeit->second.end(); ++it) + { if (it->obj) it->obj->Release(); } @@ -111,7 +120,8 @@ void ScriptEngine::deleteAllCallbacks() { } int -RoRServerScriptBuilderIncludeCallback(const char *include, const char *from, CScriptBuilder *builder, void *userParam) { +RoRServerScriptBuilderIncludeCallback(const char *include, const char *from, CScriptBuilder *builder, void *userParam) +{ // Resource directory needs to be set in the config if (Config::getResourceDir().empty() || Config::getResourceDir() == "/") return -1; @@ -122,9 +132,10 @@ RoRServerScriptBuilderIncludeCallback(const char *include, const char *from, CSc if (myFilename.length() > 3 && myFilename.substr(myFilename.length() - 3, 3) == ".as") myFilename = myFilename.substr(0, myFilename.length() - 3); - // Replace all forbidden characters in the filename + // Replace all forbidden characters in the filename std::string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; - for (std::string::iterator it = myFilename.begin(); it < myFilename.end(); ++it) { + for (std::string::iterator it = myFilename.begin(); it < myFilename.end(); ++it) + { if (allowedChars.find(*it) == std::string::npos) *it = '_'; } @@ -136,30 +147,34 @@ RoRServerScriptBuilderIncludeCallback(const char *include, const char *from, CSc return r; return 1; - } -int ScriptEngine::loadScript(std::string scriptname) { - if (scriptname.empty()) return 0; +int ScriptEngine::loadScript(std::string scriptname) +{ + if (scriptname.empty()) + return 0; - int r; + int r; CScriptBuilder builder; builder.SetIncludeCallback(RoRServerScriptBuilderIncludeCallback, NULL); r = builder.StartNewModule(engine, "script"); - if (r < 0) { + if (r < 0) + { Logger::Log(LOG_ERROR, "ScriptEngine: Unknown error while starting a new script module."); return 1; } r = builder.AddSectionFromFile(scriptname.c_str()); - if (r < 0) { + if (r < 0) + { Logger::Log(LOG_ERROR, "ScriptEngine: Unknown error while adding a new section from file."); return 1; } r = builder.BuildModule(); - if (r < 0) { + if (r < 0) + { if (r == asINVALID_CONFIGURATION) Logger::Log(LOG_ERROR, "ScriptEngine: The engine configuration is invalid."); @@ -186,22 +201,28 @@ int ScriptEngine::loadScript(std::string scriptname) { asIScriptFunction *func; func = mod->GetFunctionByDecl("void frameStep(float)"); - if (func) addCallback("frameStep", func, NULL); + if (func) + addCallback("frameStep", func, NULL); func = mod->GetFunctionByDecl("void playerDeleted(int, int)"); - if (func) addCallback("playerDeleted", func, NULL); + if (func) + addCallback("playerDeleted", func, NULL); func = mod->GetFunctionByDecl("void playerAdded(int)"); - if (func) addCallback("playerAdded", func, NULL); + if (func) + addCallback("playerAdded", func, NULL); func = mod->GetFunctionByDecl("int streamAdded(int, RoRnet::StreamRegister@)"); - if (func) addCallback("streamAdded", func, NULL); + if (func) + addCallback("streamAdded", func, NULL); func = mod->GetFunctionByDecl("int playerChat(int, string msg)"); - if (func) addCallback("playerChat", func, NULL); + if (func) + addCallback("playerChat", func, NULL); func = mod->GetFunctionByDecl("void gameCmd(int, string)"); - if (func) addCallback("gameCmd", func, NULL); + if (func) + addCallback("gameCmd", func, NULL); // Create and configure our context context = engine->CreateContext(); @@ -210,7 +231,8 @@ int ScriptEngine::loadScript(std::string scriptname) { // Find the function that is to be called. func = mod->GetFunctionByDecl("void main()"); - if (!func) { + if (!func) + { // The function couldn't be found. Instruct the script writer to include the // expected function in the script. Logger::Log(LOG_WARN, @@ -222,21 +244,21 @@ int ScriptEngine::loadScript(std::string scriptname) { context->Prepare(func); Logger::Log(LOG_INFO, "ScriptEngine: Executing main()"); r = context->Execute(); - if (r != asEXECUTION_FINISHED) { + if (r != asEXECUTION_FINISHED) // The execution didn't complete as expected. Determine what happened. - if (r == asEXECUTION_EXCEPTION) { + if (r == asEXECUTION_EXCEPTION) // An exception occurred, let the script writer know what happened so it can be corrected. Logger::Log(LOG_ERROR, "ScriptEngine: An exception '%s' occurred. Please correct the code in file '%s' and try again.", context->GetExceptionString(), scriptname.c_str()); - } - } return 0; } -void ScriptEngine::ExceptionCallback(asIScriptContext *ctx, void *param) { +void ScriptEngine::ExceptionCallback(asIScriptContext *ctx, void *param) +{ const asIScriptFunction *function = ctx->GetExceptionFunction(); + Logger::Log(LOG_INFO, "--- exception ---"); Logger::Log(LOG_INFO, "desc: %s", ctx->GetExceptionString()); Logger::Log(LOG_INFO, "func: %s", function->GetDeclaration()); @@ -248,7 +270,8 @@ void ScriptEngine::ExceptionCallback(asIScriptContext *ctx, void *param) { // Show the call stack with the variables Logger::Log(LOG_INFO, "--- call stack ---"); char tmp[2048] = ""; - for (asUINT n = 0; n < ctx->GetCallstackSize(); n++) { + for (asUINT n = 0; n < ctx->GetCallstackSize(); n++) + { function = ctx->GetFunction(n); sprintf(tmp, "%s (%d): %s", function->GetScriptSectionName(), ctx->GetLineNumber(n), function->GetDeclaration()); @@ -258,15 +281,19 @@ void ScriptEngine::ExceptionCallback(asIScriptContext *ctx, void *param) { Logger::Log(LOG_INFO, "--- end of script exception message ---"); } -void ScriptEngine::LineCallback(asIScriptContext *ctx, void *param) { - char tmp[1024] = ""; - asIScriptEngine *engine = ctx->GetEngine(); - int col; - const char *sectionName; - int line = ctx->GetLineNumber(0, &col, §ionName); - int indent = ctx->GetCallstackSize(); +void ScriptEngine::LineCallback(asIScriptContext *ctx, void *param) +{ + char tmp[1024] = ""; + asIScriptEngine *engine = ctx->GetEngine(); + int col; + const char *sectionName; + int line = ctx->GetLineNumber(0, &col, §ionName); + int indent = ctx->GetCallstackSize(); + for (int n = 0; n < indent; n++) + { sprintf(tmp + n, " "); + } const asIScriptFunction *function = engine->GetFunctionById(0); sprintf(tmp + indent, "%s:%s:%s:%d,%d", function->GetModuleName(), sectionName, function->GetDeclaration(), @@ -275,48 +302,60 @@ void ScriptEngine::LineCallback(asIScriptContext *ctx, void *param) { strcat(tmp, ""); Logger::Log(LOG_INFO, tmp); -// PrintVariables(ctx, -1); + // PrintVariables(ctx, -1); } -void ScriptEngine::PrintVariables(asIScriptContext *ctx, int stackLevel) { +void ScriptEngine::PrintVariables(asIScriptContext *ctx, int stackLevel) +{ asIScriptEngine *engine = ctx->GetEngine(); // First print the this pointer if this is a class method - int typeId = ctx->GetThisTypeId(stackLevel); + int typeId = ctx->GetThisTypeId(stackLevel); void *varPointer = ctx->GetThisPointer(stackLevel); - if (typeId) { + + if (typeId) Logger::Log(LOG_INFO, " this = 0x%x", varPointer); - } // Print the value of each variable, including parameters int numVars = ctx->GetVarCount(stackLevel); - for (int n = 0; n < numVars; n++) { - int typeId = ctx->GetVarTypeId(n, stackLevel); + for (int n = 0; n < numVars; n++) + { + int typeId = ctx->GetVarTypeId(n, stackLevel); void *varPointer = ctx->GetAddressOfVar(n, stackLevel); - if (typeId == asTYPEID_INT32) { - Logger::Log(LOG_INFO, " %s = %d", ctx->GetVarDeclaration(n, stackLevel), *(int *) varPointer); - } else if (typeId == asTYPEID_FLOAT) { - Logger::Log(LOG_INFO, " %s = %f", ctx->GetVarDeclaration(n, stackLevel), *(float *) varPointer); - } else if (typeId & asTYPEID_SCRIPTOBJECT) { - asIScriptObject *obj = (asIScriptObject *) varPointer; + if (typeId == asTYPEID_INT32) + { + Logger::Log(LOG_INFO, " %s = %d", ctx->GetVarDeclaration(n, stackLevel), *(int*)varPointer); + } + else if (typeId == asTYPEID_FLOAT) + { + Logger::Log(LOG_INFO, " %s = %f", ctx->GetVarDeclaration(n, stackLevel), *(float*)varPointer); + } + else if (typeId & asTYPEID_SCRIPTOBJECT) + { + asIScriptObject *obj = (asIScriptObject*)varPointer; if (obj) Logger::Log(LOG_INFO, " %s = {...}", ctx->GetVarDeclaration(n, stackLevel)); else Logger::Log(LOG_INFO, " %s = ", ctx->GetVarDeclaration(n, stackLevel)); - } else if (typeId == engine->GetTypeIdByDecl("string")) { - std::string *str = (std::string *) varPointer; + } + else if (typeId == engine->GetTypeIdByDecl("string")) + { + std::string *str = (std::string*)varPointer; if (str) Logger::Log(LOG_INFO, " %s = '%s'", ctx->GetVarDeclaration(n, stackLevel), str->c_str()); else Logger::Log(LOG_INFO, " %s = ", ctx->GetVarDeclaration(n, stackLevel)); - } else { + } + else + { Logger::Log(LOG_INFO, " %s = {...}", ctx->GetVarDeclaration(n, stackLevel)); } } } // continue with initializing everything -void ScriptEngine::init() { +void ScriptEngine::init() +{ int result; // Create the script engine @@ -327,13 +366,17 @@ void ScriptEngine::init() { // some registration fails the engine may send valuable information to the message // stream. result = engine->SetMessageCallback(asMETHOD(ScriptEngine, msgCallback), this, asCALL_THISCALL); - if (result < 0) { - if (result == asINVALID_ARG) { + if (result < 0) + { + if (result == asINVALID_ARG) + { Logger::Log(LOG_ERROR, "ScriptEngine: One of the arguments is incorrect, e.g. obj is null for a class method."); return; - } else if (result == asNOT_SUPPORTED) { - Logger::Log(LOG_ERROR, "ScriptEngine: The arguments are not supported, e.g. asCALL_GENERIC."); + } + else if (result == asNOT_SUPPORTED) + { + Logger::Log(LOG_ERROR, "ScriptEngine: The arguments are not supported, e.g. asCALL_GENERIC."); return; } Logger::Log(LOG_ERROR, "ScriptEngine: Unknown error while setting up message callback"); @@ -345,10 +388,9 @@ void ScriptEngine::init() { // The SDK do however provide a standard add-on for registering a string type, so it's not // necessary to register your own string type if you don't want to. RegisterStdString(engine); - RegisterScriptArray(engine, - true); // true = allow arrays to be registered as type[] (e.g. int[]). Needed for backwards compatibillity. - RegisterStdStringUtils(engine); // depends on string and array - RegisterScriptMath3D(engine); // depends on string + RegisterScriptArray(engine, true); // true = allow arrays to be registered as type[] (e.g. int[]). Needed for backwards compatibillity. + RegisterStdStringUtils(engine); // depends on string and array + RegisterScriptMath3D(engine); // depends on string RegisterScriptMath(engine); RegisterScriptDictionary(engine); RegisterScriptFile(engine); @@ -482,7 +524,7 @@ void ScriptEngine::init() { assert_net(result >= 0); result = engine->RegisterObjectMethod("RoRnet::StreamRegister", "string getName()", asFUNCTION(stream_register_get_name), asCALL_CDECL_OBJFIRST); - assert_net(result >= 0); // (No property accessor on purpose) + assert_net(result >= 0); // (No property accessor on purpose) result = engine->RegisterObjectProperty("RoRnet::StreamRegister", "int type", offsetof(RoRnet::StreamRegister, type)); assert_net(result >= 0); @@ -552,15 +594,17 @@ void ScriptEngine::init() { assert_net(result >= 0); // register constants - result = engine->RegisterGlobalProperty("const int TO_ALL", (void *) &TO_ALL); + result = engine->RegisterGlobalProperty("const int TO_ALL", (void*)&TO_ALL); assert_net(result >= 0); Logger::Log(LOG_INFO, "ScriptEngine: Registration done"); } -void ScriptEngine::msgCallback(const asSMessageInfo *msg) { +void ScriptEngine::msgCallback(const asSMessageInfo *msg) +{ const char *type = "Error"; + if (msg->type == asMSGTYPE_INFORMATION) type = "Info"; else if (msg->type == asMSGTYPE_WARNING) @@ -570,9 +614,12 @@ void ScriptEngine::msgCallback(const asSMessageInfo *msg) { } // unused method -int ScriptEngine::loadScriptFile(const char *fileName, string &script) { +int ScriptEngine::loadScriptFile(const char *fileName, string &script) +{ FILE *f = fopen(fileName, "rb"); - if (!f) return 1; + + if (!f) + return 1; // Determine the size of the file fseek(f, 0, SEEK_END); @@ -588,41 +635,51 @@ int ScriptEngine::loadScriptFile(const char *fileName, string &script) { } // unused method -int ScriptEngine::executeString(std::string command) { +int ScriptEngine::executeString(std::string command) +{ // This method would work if you include the scriptHelper add-on #if 0 - if(!engine) return 0; - if(!context) context = engine->CreateContext(); - asIScriptModule* mod = engine->GetModule("script", asGM_CREATE_IF_NOT_EXISTS); - int result = ExecuteString(engine, command.c_str(), mod, context); - if(result<0) - { + if (!engine) + return 0; + + if (!context) + context = engine->CreateContext(); + asIScriptModule* mod = engine->GetModule("script", asGM_CREATE_IF_NOT_EXISTS); + int result = ExecuteString(engine, command.c_str(), mod, context); + if (result < 0) Logger::Log(LOG_ERROR, "ScriptEngine: Error while executing string: '" + command + "'."); - } return result; #endif // 0 return 0; } -int ScriptEngine::framestep(float dt) { - if (!engine) return 0; +int ScriptEngine::framestep(float dt) +{ + if (!engine) + return 0; + MutexLocker scoped_lock(context_mutex); - if (!context) context = engine->CreateContext(); + if (!context) + context = engine->CreateContext(); int r; // Copy the callback list, because the callback list itself may get changed while executing the script callbackList queue(callbacks["frameStep"]); // loop over all callbacks - for (unsigned int i = 0; i < queue.size(); ++i) { + for (unsigned int i = 0; i < queue.size(); ++i) + { // prepare the call r = context->Prepare(queue[i].func); - if (r < 0) continue; + if (r < 0) + continue; // Set the object if present (if we don't set it, then we call a global function) - if (queue[i].obj != NULL) { + if (queue[i].obj != NULL) + { context->SetObject(queue[i].obj); - if (r < 0) continue; + if (r < 0) + continue; } // Set the arguments @@ -638,31 +695,42 @@ int ScriptEngine::framestep(float dt) { return 0; } -void ScriptEngine::playerDeleted(int uid, int crash, bool doNestedCall /*= false*/) { - if (!engine) return; - if (!doNestedCall) MutexLocker scoped_lock(context_mutex); - if (!context) context = engine->CreateContext(); +void ScriptEngine::playerDeleted(int uid, int crash, bool doNestedCall /*= false*/) +{ + if (!engine) + return; + + if (!doNestedCall) + MutexLocker scoped_lock(context_mutex); + if (!context) + context = engine->CreateContext(); int r; // Push the state of the context if this is a nested call - if (doNestedCall) { + if (doNestedCall) + { r = context->PushState(); - if (r < 0) return; + if (r < 0) + return; } // Copy the callback list, because the callback list itself may get changed while executing the script callbackList queue(callbacks["playerDeleted"]); // loop over all callbacks - for (unsigned int i = 0; i < queue.size(); ++i) { + for (unsigned int i = 0; i < queue.size(); ++i) + { // prepare the call r = context->Prepare(queue[i].func); - if (r < 0) continue; + if (r < 0) + continue; // Set the object if present (if we don't set it, then we call a global function) - if (queue[i].obj != NULL) { + if (queue[i].obj != NULL) + { context->SetObject(queue[i].obj); - if (r < 0) continue; + if (r < 0) + continue; } // Set the arguments @@ -674,34 +742,44 @@ void ScriptEngine::playerDeleted(int uid, int crash, bool doNestedCall /*= false } // Pop the state of the context if this is was a nested call - if (doNestedCall) { + if (doNestedCall) + { r = context->PopState(); - if (r < 0) return; + if (r < 0) + return; } return; } -void ScriptEngine::playerAdded(int uid) { - if (!engine) return; +void ScriptEngine::playerAdded(int uid) +{ + if (!engine) + return; + MutexLocker scoped_lock(context_mutex); - if (!context) context = engine->CreateContext(); + if (!context) + context = engine->CreateContext(); int r; // Copy the callback list, because the callback list itself may get changed while executing the script callbackList queue(callbacks["playerAdded"]); // loop over all callbacks - for (unsigned int i = 0; i < queue.size(); ++i) { + for (unsigned int i = 0; i < queue.size(); ++i) + { // prepare the call r = context->Prepare(queue[i].func); - if (r < 0) continue; + if (r < 0) + continue; // Set the object if present (if we don't set it, then we call a global function) - if (queue[i].obj != NULL) { + if (queue[i].obj != NULL) + { context->SetObject(queue[i].obj); - if (r < 0) continue; + if (r < 0) + continue; } // Set the arguments @@ -713,10 +791,14 @@ void ScriptEngine::playerAdded(int uid) { return; } -int ScriptEngine::streamAdded(int uid, RoRnet::StreamRegister *reg) { - if (!engine) return 0; +int ScriptEngine::streamAdded(int uid, RoRnet::StreamRegister *reg) +{ + if (!engine) + return 0; + MutexLocker scoped_lock(context_mutex); - if (!context) context = engine->CreateContext(); + if (!context) + context = engine->CreateContext(); int r; int ret = BROADCAST_AUTO; @@ -724,24 +806,29 @@ int ScriptEngine::streamAdded(int uid, RoRnet::StreamRegister *reg) { callbackList queue(callbacks["streamAdded"]); // loop over all callbacks - for (unsigned int i = 0; i < queue.size(); ++i) { + for (unsigned int i = 0; i < queue.size(); ++i) + { // prepare the call r = context->Prepare(queue[i].func); - if (r < 0) continue; + if (r < 0) + continue; // Set the object if present (if we don't set it, then we call a global function) - if (queue[i].obj != NULL) { + if (queue[i].obj != NULL) + { context->SetObject(queue[i].obj); - if (r < 0) continue; + if (r < 0) + continue; } // Set the arguments context->SetArgDWord(0, uid); - context->SetArgObject(1, (void *) reg); + context->SetArgObject(1, (void*)reg); // Execute it r = context->Execute(); - if (r == asEXECUTION_FINISHED) { + if (r == asEXECUTION_FINISHED) + { int newRet = context->GetReturnDWord(); // Only use the new result if it's more restrictive than what we already had @@ -753,10 +840,14 @@ int ScriptEngine::streamAdded(int uid, RoRnet::StreamRegister *reg) { return ret; } -int ScriptEngine::playerChat(int uid, std::string msg) { - if (!engine) return 0; +int ScriptEngine::playerChat(int uid, std::string msg) +{ + if (!engine) + return 0; + MutexLocker scoped_lock(context_mutex); - if (!context) context = engine->CreateContext(); + if (!context) + context = engine->CreateContext(); int r; int ret = BROADCAST_AUTO; @@ -764,25 +855,30 @@ int ScriptEngine::playerChat(int uid, std::string msg) { callbackList queue(callbacks["playerChat"]); // loop over all callbacks - for (unsigned int i = 0; i < queue.size(); ++i) { + for (unsigned int i = 0; i < queue.size(); ++i) + { // prepare the call r = context->Prepare(queue[i].func); - if (r < 0) continue; + if (r < 0) + continue; // Set the object if present (if we don't set it, then we call a global function) - if (queue[i].obj != NULL) { + if (queue[i].obj != NULL) + { context->SetObject(queue[i].obj); - if (r < 0) continue; + if (r < 0) + continue; } // Set the arguments context->SetArgDWord(0, uid); std::string msg = Str::SanitizeUtf8(msg.begin(), msg.end()); - context->SetArgObject(1, (void *) &msg); + context->SetArgObject(1, (void*)&msg); // Execute it r = context->Execute(); - if (r == asEXECUTION_FINISHED) { + if (r == asEXECUTION_FINISHED) + { int newRet = context->GetReturnDWord(); // Only use the new result if it's more restrictive than what we already had @@ -794,30 +890,38 @@ int ScriptEngine::playerChat(int uid, std::string msg) { return ret; } -void ScriptEngine::gameCmd(int uid, const std::string &cmd) { - if (!engine) return; +void ScriptEngine::gameCmd(int uid, const std::string &cmd) +{ + if (!engine) + return; + MutexLocker scoped_lock(context_mutex); - if (!context) context = engine->CreateContext(); + if (!context) + context = engine->CreateContext(); int r; // Copy the callback list, because the callback list itself may get changed while executing the script callbackList queue(callbacks["gameCmd"]); // loop over all callbacks - for (unsigned int i = 0; i < queue.size(); ++i) { + for (unsigned int i = 0; i < queue.size(); ++i) + { // prepare the call r = context->Prepare(queue[i].func); - if (r < 0) continue; + if (r < 0) + continue; // Set the object if present (if we don't set it, then we call a global function) - if (queue[i].obj != NULL) { + if (queue[i].obj != NULL) + { context->SetObject(queue[i].obj); - if (r < 0) continue; + if (r < 0) + continue; } // Set the arguments context->SetArgDWord(0, uid); - context->SetArgObject(1, (void *) &cmd); + context->SetArgObject(1, (void*)&cmd); // Execute it r = context->Execute(); @@ -826,12 +930,14 @@ void ScriptEngine::gameCmd(int uid, const std::string &cmd) { return; } -void ScriptEngine::timerLoop() { - while (!exit) { +void ScriptEngine::timerLoop() +{ + while (!exit) + { // sleep 200 miliseconds #ifndef _WIN32 usleep(200000); -#else // _WIN32 +#else // _WIN32 Sleep(200); #endif // _WIN32 // call script @@ -839,45 +945,67 @@ void ScriptEngine::timerLoop() { } } -void ScriptEngine::setException(const std::string &message) { - if (!engine || !context) { +void ScriptEngine::setException(const std::string &message) +{ + if (!engine || !context) + { // There's not much we can do, except for logging the message Logger::Log(LOG_INFO, "--- script exception ---"); Logger::Log(LOG_INFO, " desc: %s", (message.c_str())); Logger::Log(LOG_INFO, "--- end of script exception message ---"); - } else + } + else + { context->SetException(message.c_str()); + } } -void ScriptEngine::addCallbackScript(const std::string &type, const std::string &_func, asIScriptObject *obj) { - if (!engine) return; +void ScriptEngine::addCallbackScript(const std::string &type, const std::string &_func, asIScriptObject *obj) +{ + if (!engine) + return; // get the function declaration and check the type at the same time std::string funcDecl = ""; if (type == "frameStep") + { funcDecl = "void " + _func + "(float)"; + } else if (type == "playerChat") + { funcDecl = "int " + _func + "(int, const string &in)"; + } else if (type == "gameCmd") + { funcDecl = "void " + _func + "(int, const string &in)"; + } else if (type == "playerAdded") + { funcDecl = "void " + _func + "(int)"; + } else if (type == "playerDeleted") + { funcDecl = "void " + _func + "(int, int)"; + } else if (type == "streamAdded") + { funcDecl = "int " + _func + "(int, RoRnet::StreamRegister@)"; - else { + } + else + { setException("Type " + type + " does not exist! Possible type strings: 'frameStep', 'playerChat', 'gameCmd', 'playerAdded', 'playerDeleted', 'streamAdded'."); return; } asIScriptFunction *func; - if (obj) { + if (obj) + { // search for a method in the class asIObjectType *objType = obj->GetObjectType(); func = objType->GetMethodByDecl(funcDecl.c_str()); - if (!func) { + if (!func) + { // give a nice error message that says that the method was not found. func = objType->GetMethodByName(_func.c_str()); if (func) @@ -887,11 +1015,14 @@ void ScriptEngine::addCallbackScript(const std::string &type, const std::string setException("Method '" + funcDecl + "' was not found in '" + objType->GetName() + "'."); return; } - } else { + } + else + { // search for a global function asIScriptModule *mod = engine->GetModule("script"); func = mod->GetFunctionByDecl(funcDecl.c_str()); - if (!func) { + if (!func) + { // give a nice error message that says that the function was not found. func = mod->GetFunctionByName(_func.c_str()); if (func) @@ -905,29 +1036,31 @@ void ScriptEngine::addCallbackScript(const std::string &type, const std::string if (callbackExists(type, func, obj)) Logger::Log(LOG_INFO, "ScriptEngine: error: Function '" + std::string(func->GetDeclaration(false)) + - "' is already a callback for '" + type + "'."); + "' is already a callback for '" + type + "'."); else addCallback(type, func, obj); } -void ScriptEngine::addCallback(const std::string &type, asIScriptFunction *func, asIScriptObject *obj) { - if (!engine) return; +void ScriptEngine::addCallback(const std::string &type, asIScriptFunction *func, asIScriptObject *obj) +{ + if (!engine) + return; - if (obj) { + if (obj) // We're about to store a reference to the object, so let's tell the script engine about that // This avoids the object from going out of scope while we're still trying to access it. // BUT: it prevents local objects from being destroyed automatically.... engine->AddRefScriptObject(obj, obj->GetObjectType()); - } // Add the function to the list callback_t tmp; - tmp.obj = obj; + tmp.obj = obj; tmp.func = func; callbacks[type].push_back(tmp); // Do we need to start the frameStep thread? - if (type == "frameStep" && !frameStepThreadRunning) { + if (type == "frameStep" && !frameStepThreadRunning) + { frameStepThreadRunning = true; Logger::Log(LOG_DEBUG, "ScriptEngine: starting timer thread"); pthread_create(&timer_thread, NULL, s_sethreadstart, this); @@ -935,27 +1068,42 @@ void ScriptEngine::addCallback(const std::string &type, asIScriptFunction *func, // finished :) Logger::Log(LOG_INFO, "ScriptEngine: success: Added a '" + type + "' callback for: " + - std::string(func->GetDeclaration(true))); + std::string(func->GetDeclaration(true))); } -void ScriptEngine::deleteCallbackScript(const std::string &type, const std::string &_func, asIScriptObject *obj) { - if (!engine) return; +void ScriptEngine::deleteCallbackScript(const std::string &type, const std::string &_func, asIScriptObject *obj) +{ + if (!engine) + return; // get the function declaration and check the type at the same time std::string funcDecl = ""; if (type == "frameStep") + { funcDecl = "void " + _func + "(float)"; + } else if (type == "playerChat") + { funcDecl = "int " + _func + "(int, const string &in)"; + } else if (type == "gameCmd") + { funcDecl = "void " + _func + "(int, const string &in)"; + } else if (type == "playerAdded") + { funcDecl = "void " + _func + "(int)"; + } else if (type == "playerDeleted") + { funcDecl = "void " + _func + "(int, int)"; + } else if (type == "streamAdded") + { funcDecl = "int " + _func + "(int, RoRnet::StreamRegister@)"; - else { + } + else + { setException("Type " + type + " does not exist! Possible type strings: 'frameStep', 'playerChat', 'gameCmd', 'playerAdded', 'playerDeleted', 'streamAdded'."); Logger::Log(LOG_INFO, "ScriptEngine: error: Failed to remove callback: " + _func); @@ -963,11 +1111,13 @@ void ScriptEngine::deleteCallbackScript(const std::string &type, const std::stri } asIScriptFunction *func; - if (obj) { + if (obj) + { // search for a method in the class asIObjectType *objType = obj->GetObjectType(); func = objType->GetMethodByDecl(funcDecl.c_str()); - if (!func) { + if (!func) + { // give a nice error message that says that the method was not found. func = objType->GetMethodByName(_func.c_str()); if (func) @@ -978,11 +1128,14 @@ void ScriptEngine::deleteCallbackScript(const std::string &type, const std::stri Logger::Log(LOG_INFO, "ScriptEngine: error: Failed to remove callback: " + funcDecl); return; } - } else { + } + else + { // search for a global function asIScriptModule *mod = engine->GetModule("script"); func = mod->GetFunctionByDecl(funcDecl.c_str()); - if (!func) { + if (!func) + { // give a nice error message that says that the function was not found. func = mod->GetFunctionByName(_func.c_str()); if (func) @@ -997,14 +1150,18 @@ void ScriptEngine::deleteCallbackScript(const std::string &type, const std::stri deleteCallback(type, func, obj); } -void ScriptEngine::deleteCallback(const std::string &type, asIScriptFunction *func, asIScriptObject *obj) { - if (!engine) return; +void ScriptEngine::deleteCallback(const std::string &type, asIScriptFunction *func, asIScriptObject *obj) +{ + if (!engine) + return; - for (callbackList::iterator it = callbacks[type].begin(); it != callbacks[type].end(); ++it) { - if (it->obj == obj && it->func == func) { + for (callbackList::iterator it = callbacks[type].begin(); it != callbacks[type].end(); ++it) + { + if (it->obj == obj && it->func == func) + { callbacks[type].erase(it); Logger::Log(LOG_INFO, "ScriptEngine: success: removed a '" + type + "' callback: " + - std::string(func->GetDeclaration(true))); + std::string(func->GetDeclaration(true))); if (obj) engine->ReleaseScriptObject(obj, obj->GetObjectType()); return; @@ -1013,10 +1170,13 @@ void ScriptEngine::deleteCallback(const std::string &type, asIScriptFunction *fu Logger::Log(LOG_INFO, "ScriptEngine: error: failed to remove callback: " + std::string(func->GetDeclaration(true))); } -bool ScriptEngine::callbackExists(const std::string &type, asIScriptFunction *func, asIScriptObject *obj) { - if (!engine) return false; +bool ScriptEngine::callbackExists(const std::string &type, asIScriptFunction *func, asIScriptObject *obj) +{ + if (!engine) + return false; - for (callbackList::iterator it = callbacks[type].begin(); it != callbacks[type].end(); ++it) { + for (callbackList::iterator it = callbacks[type].begin(); it != callbacks[type].end(); ++it) + { if (it->obj == obj && it->func == func) return true; } @@ -1024,199 +1184,286 @@ bool ScriptEngine::callbackExists(const std::string &type, asIScriptFunction *fu } /* class that implements the interface for the scripts */ -ServerScript::ServerScript(ScriptEngine *se, Sequencer *seq) : mse(se), seq(seq) { +ServerScript::ServerScript(ScriptEngine *se, Sequencer *seq) : mse(se), seq(seq) +{ } -ServerScript::~ServerScript() { +ServerScript::~ServerScript() +{ } -void ServerScript::log(std::string &msg) { +void ServerScript::log(std::string &msg) +{ Logger::Log(LOG_INFO, "SCRIPT|%s", msg.c_str()); } -void ServerScript::say(std::string &msg, int uid, int type) { +void ServerScript::say(std::string &msg, int uid, int type) +{ seq->serverSayThreadSave(msg, uid, type); } -void ServerScript::kick(int kuid, std::string &msg) { +void ServerScript::kick(int kuid, std::string &msg) +{ seq->disconnect(kuid, msg.c_str(), false, false); mse->playerDeleted(kuid, 0, true); } -void ServerScript::ban(int buid, std::string &msg) { +void ServerScript::ban(int buid, std::string &msg) +{ seq->SilentBan(buid, msg.c_str(), false); mse->playerDeleted(buid, 0, true); } -bool ServerScript::unban(int buid) { +bool ServerScript::unban(int buid) +{ return seq->UnBan(buid); } -std::string ServerScript::getUserName(int uid) { +std::string ServerScript::getUserName(int uid) +{ Client *c = seq->getClient(uid); - if (!c) return ""; + + if (!c) + return ""; return Str::SanitizeUtf8(c->user.username); } -void ServerScript::setUserName(int uid, const string &username) { +void ServerScript::setUserName(int uid, const string &username) +{ Client *c = seq->getClient(uid); - if (!c) return; + + if (!c) + return; + std::string username_sane = Str::SanitizeUtf8(username.begin(), username.end()); strncpy(c->user.username, username_sane.c_str(), RORNET_MAX_USERNAME_LEN); } -std::string ServerScript::getUserAuth(int uid) { +std::string ServerScript::getUserAuth(int uid) +{ Client *c = seq->getClient(uid); - if (!c) return "none"; - if (c->user.authstatus & RoRnet::AUTH_ADMIN) return "admin"; - else if (c->user.authstatus & RoRnet::AUTH_MOD) return "moderator"; - else if (c->user.authstatus & RoRnet::AUTH_RANKED) return "ranked"; - else if (c->user.authstatus & RoRnet::AUTH_BOT) return "bot"; - //else if(c->user.authstatus & RoRnet::AUTH_NONE) + + if (!c) + return "none"; + + if (c->user.authstatus & RoRnet::AUTH_ADMIN) + return "admin"; + else if (c->user.authstatus & RoRnet::AUTH_MOD) + return "moderator"; + else if (c->user.authstatus & RoRnet::AUTH_RANKED) + return "ranked"; + else if (c->user.authstatus & RoRnet::AUTH_BOT) + return "bot"; + + //else if(c->user.authstatus & RoRnet::AUTH_NONE) return "none"; } -int ServerScript::getUserAuthRaw(int uid) { +int ServerScript::getUserAuthRaw(int uid) +{ Client *c = seq->getClient(uid); - if (!c) return RoRnet::AUTH_NONE; + + if (!c) + return RoRnet::AUTH_NONE; + return c->user.authstatus; } -void ServerScript::setUserAuthRaw(int uid, int authmode) { +void ServerScript::setUserAuthRaw(int uid, int authmode) +{ Client *c = seq->getClient(uid); - if (!c) return; + + if (!c) + return; + c->user.authstatus = authmode & ~(RoRnet::AUTH_RANKED | RoRnet::AUTH_BANNED); } -int ServerScript::getUserColourNum(int uid) { +int ServerScript::getUserColourNum(int uid) +{ Client *c = seq->getClient(uid); - if (!c) return 0; + + if (!c) + return 0; + return c->user.colournum; } -void ServerScript::setUserColourNum(int uid, int num) { +void ServerScript::setUserColourNum(int uid, int num) +{ Client *c = seq->getClient(uid); - if (!c) return; + + if (!c) + return; + c->user.colournum = num; } -std::string ServerScript::getUserToken(int uid) { +std::string ServerScript::getUserToken(int uid) +{ Client *c = seq->getClient(uid); - if (!c) return 0; + + if (!c) + return 0; + return std::string(c->user.usertoken, 40); } -std::string ServerScript::getUserVersion(int uid) { +std::string ServerScript::getUserVersion(int uid) +{ Client *c = seq->getClient(uid); - if (!c) return 0; + + if (!c) + return 0; + return std::string(c->user.clientversion, 25); } -std::string ServerScript::getUserIPAddress(int uid) { +std::string ServerScript::getUserIPAddress(int uid) +{ Client *client = seq->getClient(uid); - if (client != nullptr) { + + if (client != nullptr) return client->GetIpAddress(); - } + return ""; } -std::string ServerScript::getServerTerrain() { +std::string ServerScript::getServerTerrain() +{ return Config::getTerrainName(); } -int ServerScript::sendGameCommand(int uid, std::string cmd) { +int ServerScript::sendGameCommand(int uid, std::string cmd) +{ return seq->sendGameCommand(uid, cmd); } -int ServerScript::getNumClients() { +int ServerScript::getNumClients() +{ return seq->getNumClients(); } -int ServerScript::getStartTime() { +int ServerScript::getStartTime() +{ return seq->getStartTime(); } -int ServerScript::getTime() { +int ServerScript::getTime() +{ return Messaging::getTime(); } -void ServerScript::deleteCallback(const std::string &type, const std::string &func, void *obj, int refTypeId) { - if (refTypeId & asTYPEID_SCRIPTOBJECT && (refTypeId & asTYPEID_OBJHANDLE)) { - mse->deleteCallbackScript(type, func, *(asIScriptObject **) obj); - } else if (refTypeId == asTYPEID_VOID) { +void ServerScript::deleteCallback(const std::string &type, const std::string &func, void *obj, int refTypeId) +{ + if (refTypeId & asTYPEID_SCRIPTOBJECT && (refTypeId & asTYPEID_OBJHANDLE)) + mse->deleteCallbackScript(type, func, *(asIScriptObject**)obj); + else if (refTypeId == asTYPEID_VOID) mse->deleteCallbackScript(type, func, NULL); - } else if (refTypeId & asTYPEID_SCRIPTOBJECT) { + else if (refTypeId & asTYPEID_SCRIPTOBJECT) // We received an object instead of a handle of the object. // We cannot allow this because this will crash if the deleteCallback is called from inside a constructor of a global variable. mse->setException( - "server.deleteCallback should be called with a handle of the object! (that is: put an @ sign in front of the object)"); + "server.deleteCallback should be called with a handle of the object! (that is: put an @ sign in front of the object)"); - // uncomment to enable anyway: - //mse->deleteCallbackScript(type, func, (asIScriptObject*)obj); - } else { + // uncomment to enable anyway: + //mse->deleteCallbackScript(type, func, (asIScriptObject*)obj); + else mse->setException("The object for the callback has to be a script-class or null!"); - } } -void ServerScript::setCallback(const std::string &type, const std::string &func, void *obj, int refTypeId) { - if (refTypeId & asTYPEID_SCRIPTOBJECT && (refTypeId & asTYPEID_OBJHANDLE)) { - mse->addCallbackScript(type, func, *(asIScriptObject **) obj); - } else if (refTypeId == asTYPEID_VOID) { +void ServerScript::setCallback(const std::string &type, const std::string &func, void *obj, int refTypeId) +{ + if (refTypeId & asTYPEID_SCRIPTOBJECT && (refTypeId & asTYPEID_OBJHANDLE)) + mse->addCallbackScript(type, func, *(asIScriptObject**)obj); + else if (refTypeId == asTYPEID_VOID) mse->addCallbackScript(type, func, NULL); - } else if (refTypeId & asTYPEID_SCRIPTOBJECT) { + else if (refTypeId & asTYPEID_SCRIPTOBJECT) // We received an object instead of a handle of the object. // We cannot allow this because this will crash if the setCallback is called from inside a constructor of a global variable. mse->setException( - "server.setCallback should be called with a handle of the object! (that is: put an @ sign in front of the object)"); + "server.setCallback should be called with a handle of the object! (that is: put an @ sign in front of the object)"); - // uncomment to enable anyway: - //mse->addCallbackScript(type, func, (asIScriptObject*)obj); - } else { + // uncomment to enable anyway: + //mse->addCallbackScript(type, func, (asIScriptObject*)obj); + else mse->setException("The object for the callback has to be a script-class or null!"); - } } -void ServerScript::throwException(const std::string &message) { +void ServerScript::throwException(const std::string &message) +{ mse->setException(message); } -std::string ServerScript::get_version() { +std::string ServerScript::get_version() +{ return std::string(VERSION); } -std::string ServerScript::get_asVersion() { +std::string ServerScript::get_asVersion() +{ return std::string(ANGELSCRIPT_VERSION_STRING); } -std::string ServerScript::get_protocolVersion() { +std::string ServerScript::get_protocolVersion() +{ return std::string(RORNET_VERSION); } -unsigned int ServerScript::get_maxClients() { return Config::getMaxClients(); } +unsigned int ServerScript::get_maxClients() +{ + return Config::getMaxClients(); +} -std::string ServerScript::get_serverName() { return Config::getServerName(); } +std::string ServerScript::get_serverName() +{ + return Config::getServerName(); +} -std::string ServerScript::get_IPAddr() { return Config::getIPAddr(); } +std::string ServerScript::get_IPAddr() +{ + return Config::getIPAddr(); +} -unsigned int ServerScript::get_listenPort() { return Config::getListenPort(); } +unsigned int ServerScript::get_listenPort() +{ + return Config::getListenPort(); +} -int ServerScript::get_serverMode() { return Config::getServerMode(); } +int ServerScript::get_serverMode() +{ + return Config::getServerMode(); +} -std::string ServerScript::get_owner() { return Config::getOwner(); } +std::string ServerScript::get_owner() +{ + return Config::getOwner(); +} -std::string ServerScript::get_website() { return Config::getWebsite(); } +std::string ServerScript::get_website() +{ + return Config::getWebsite(); +} -std::string ServerScript::get_ircServ() { return Config::getIRC(); } +std::string ServerScript::get_ircServ() +{ + return Config::getIRC(); +} -std::string ServerScript::get_voipServ() { return Config::getVoIP(); } +std::string ServerScript::get_voipServ() +{ + return Config::getVoIP(); +} -int ServerScript::rangeRandomInt(int from, int to) { - return (int) (from + (to - from) * ((float) rand() / (float) RAND_MAX)); +int ServerScript::rangeRandomInt(int from, int to) +{ + return (int)(from + (to - from) * ((float)rand() / (float)RAND_MAX)); } -void ServerScript::broadcastUserInfo(int uid) { +void ServerScript::broadcastUserInfo(int uid) +{ seq->broadcastUserInfo(uid); } diff --git a/source/server/ScriptEngine.h b/source/server/ScriptEngine.h index f345bfa2..550d1b5c 100644 --- a/source/server/ScriptEngine.h +++ b/source/server/ScriptEngine.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -40,13 +40,15 @@ class Sequencer; /** * This struct holds the information for a script callback. */ -struct callback_t { - asIScriptObject *obj; //!< The object instance that will need to be used with the function. +struct callback_t +{ + asIScriptObject *obj; //!< The object instance that will need to be used with the function. asIScriptFunction *func; //!< The function or method pointer that will be called. }; -typedef std::vector callbackList; +typedef std::vector callbackList; -class ScriptEngine { +class ScriptEngine +{ public: ScriptEngine(Sequencer *seq); @@ -78,7 +80,10 @@ class ScriptEngine { * Gets the currently used AngelScript script engine. * @return a pointer to the currently used AngelScript script engine */ - asIScriptEngine *getEngine() { return engine; }; + asIScriptEngine *getEngine() + { + return engine; + }; /** * Sets an exception that aborts the currently running script and shows the exception in the log file. @@ -133,14 +138,14 @@ class ScriptEngine { bool callbackExists(const std::string &type, asIScriptFunction *func, asIScriptObject *obj); protected: - Sequencer *seq; - asIScriptEngine *engine; //!< instance of the scripting engine - asIScriptContext *context; //!< context in which all scripting happens - Mutex context_mutex; //!< mutex used for locking access to the context - bool frameStepThreadRunning; //!< indicates whether the thread for the frameStep is running or not - bool exit; //!< indicates whether the script engine is shutting down - pthread_t timer_thread; - std::map callbacks; //!< A map containing the script callbacks by type. + Sequencer *seq; + asIScriptEngine *engine; //!< instance of the scripting engine + asIScriptContext *context; //!< context in which all scripting happens + Mutex context_mutex; //!< mutex used for locking access to the context + bool frameStepThreadRunning; //!< indicates whether the thread for the frameStep is running or not + bool exit; //!< indicates whether the script engine is shutting down + pthread_t timer_thread; + std::map callbacks; //!< A map containing the script callbacks by type. /** * This function initialzies the engine and registeres all types @@ -184,10 +189,11 @@ class ScriptEngine { void LineCallback(asIScriptContext *ctx, void *param); }; -class ServerScript { +class ServerScript +{ protected: - ScriptEngine *mse; //!< local script engine pointer, used as proxy mostly - Sequencer *seq; //!< local pointer to the main ExampleFrameListener, used as proxy mostly + ScriptEngine *mse; //!< local script engine pointer, used as proxy mostly + Sequencer *seq; //!< local pointer to the main ExampleFrameListener, used as proxy mostly public: ServerScript(ScriptEngine *se, Sequencer *seq); @@ -274,4 +280,3 @@ class ServerScript { }; #endif // WITH_ANGELSCRIPT - diff --git a/source/server/ScriptFileSafe.cpp b/source/server/ScriptFileSafe.cpp index 2104cd57..57677642 100644 --- a/source/server/ScriptFileSafe.cpp +++ b/source/server/ScriptFileSafe.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ // copied from the angelscript library and edited for use in Rigs of Rods Multiplayer Server // 01 Jan 2012 @@ -43,137 +43,184 @@ using namespace std; BEGIN_AS_NAMESPACE -ScriptFileSafe *ScriptFile_Factory() { +ScriptFileSafe *ScriptFile_Factory() +{ return new ScriptFileSafe(); } -void ScriptFile_Factory_Generic(asIScriptGeneric *gen) { - *(ScriptFileSafe **) gen->GetAddressOfReturnLocation() = ScriptFile_Factory(); +void ScriptFile_Factory_Generic(asIScriptGeneric *gen) +{ + *(ScriptFileSafe**)gen->GetAddressOfReturnLocation() = ScriptFile_Factory(); } -void ScriptFile_AddRef_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); +void ScriptFile_AddRef_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + file->AddRef(); } -void ScriptFile_Release_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); +void ScriptFile_Release_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + file->Release(); } -void ScriptFile_Open_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - std::string *f = (std::string *) gen->GetArgAddress(0); - std::string *m = (std::string *) gen->GetArgAddress(1); - int r = file->Open(*f, *m); +void ScriptFile_Open_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + + std::string *f = (std::string*)gen->GetArgAddress(0); + std::string *m = (std::string*)gen->GetArgAddress(1); + int r = file->Open(*f, *m); + gen->SetReturnDWord(r); } -void ScriptFile_Close_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - int r = file->Close(); +void ScriptFile_Close_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + int r = file->Close(); + gen->SetReturnDWord(r); } -void ScriptFile_GetSize_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - int r = file->GetSize(); +void ScriptFile_GetSize_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + int r = file->GetSize(); + gen->SetReturnDWord(r); } -void ScriptFile_ReadString_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - int len = gen->GetArgDWord(0); - std::string *str = (std::string *) gen->GetArgAddress(1); +void ScriptFile_ReadString_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + int len = gen->GetArgDWord(0); + + std::string *str = (std::string*)gen->GetArgAddress(1); + len = file->ReadString(len, *str); gen->SetReturnDWord(len); } -void ScriptFile_ReadLine_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - std::string *str = (std::string *) gen->GetArgAddress(0); - int len = file->ReadLine(*str); +void ScriptFile_ReadLine_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + + std::string *str = (std::string*)gen->GetArgAddress(0); + int len = file->ReadLine(*str); + gen->SetReturnDWord(len); } -void ScriptFile_ReadInt_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - asUINT bytes = *(asUINT *) gen->GetAddressOfArg(0); - *(asINT64 *) gen->GetAddressOfReturnLocation() = file->ReadInt(bytes); +void ScriptFile_ReadInt_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + asUINT bytes = *(asUINT*)gen->GetAddressOfArg(0); + + *(asINT64*)gen->GetAddressOfReturnLocation() = file->ReadInt(bytes); } -void ScriptFile_ReadUInt_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - asUINT bytes = *(asUINT *) gen->GetAddressOfArg(0); - *(asQWORD *) gen->GetAddressOfReturnLocation() = file->ReadUInt(bytes); +void ScriptFile_ReadUInt_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + asUINT bytes = *(asUINT*)gen->GetAddressOfArg(0); + + *(asQWORD*)gen->GetAddressOfReturnLocation() = file->ReadUInt(bytes); } -void ScriptFile_ReadFloat_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - *(float *) gen->GetAddressOfReturnLocation() = file->ReadFloat(); +void ScriptFile_ReadFloat_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + + *(float*)gen->GetAddressOfReturnLocation() = file->ReadFloat(); } -void ScriptFile_ReadDouble_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - *(double *) gen->GetAddressOfReturnLocation() = file->ReadDouble(); +void ScriptFile_ReadDouble_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + + *(double*)gen->GetAddressOfReturnLocation() = file->ReadDouble(); } -void ScriptFile_WriteString_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - std::string *str = (std::string *) gen->GetArgAddress(0); +void ScriptFile_WriteString_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + + std::string *str = (std::string*)gen->GetArgAddress(0); + gen->SetReturnDWord(file->WriteString(*str)); } -void ScriptFile_WriteInt_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - asINT64 val = *(asINT64 *) gen->GetAddressOfArg(0); - asUINT bytes = *(asUINT *) gen->GetAddressOfArg(1); - *(int *) gen->GetAddressOfReturnLocation() = file->WriteInt(val, bytes); +void ScriptFile_WriteInt_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + asINT64 val = *(asINT64*)gen->GetAddressOfArg(0); + asUINT bytes = *(asUINT*)gen->GetAddressOfArg(1); + + *(int*)gen->GetAddressOfReturnLocation() = file->WriteInt(val, bytes); } -void ScriptFile_WriteUInt_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - asQWORD val = *(asQWORD *) gen->GetAddressOfArg(0); - asUINT bytes = *(asUINT *) gen->GetAddressOfArg(1); - *(int *) gen->GetAddressOfReturnLocation() = file->WriteUInt(val, bytes); +void ScriptFile_WriteUInt_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + asQWORD val = *(asQWORD*)gen->GetAddressOfArg(0); + asUINT bytes = *(asUINT*)gen->GetAddressOfArg(1); + + *(int*)gen->GetAddressOfReturnLocation() = file->WriteUInt(val, bytes); } -void ScriptFile_WriteFloat_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - float val = *(float *) gen->GetAddressOfArg(0); - *(int *) gen->GetAddressOfReturnLocation() = file->WriteFloat(val); +void ScriptFile_WriteFloat_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + float val = *(float*)gen->GetAddressOfArg(0); + + *(int*)gen->GetAddressOfReturnLocation() = file->WriteFloat(val); } -void ScriptFile_WriteDouble_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - double val = *(double *) gen->GetAddressOfArg(0); - *(int *) gen->GetAddressOfReturnLocation() = file->WriteDouble(val); +void ScriptFile_WriteDouble_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + double val = *(double*)gen->GetAddressOfArg(0); + + *(int*)gen->GetAddressOfReturnLocation() = file->WriteDouble(val); } -void ScriptFile_IsEOF_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - bool r = file->IsEOF(); +void ScriptFile_IsEOF_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + bool r = file->IsEOF(); + gen->SetReturnByte(r); } -void ScriptFile_GetPos_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); +void ScriptFile_GetPos_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + gen->SetReturnDWord(file->GetPos()); } -void ScriptFile_SetPos_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - int pos = (int) gen->GetArgDWord(0); +void ScriptFile_SetPos_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + int pos = (int)gen->GetArgDWord(0); + gen->SetReturnDWord(file->SetPos(pos)); } -void ScriptFile_MovePos_Generic(asIScriptGeneric *gen) { - ScriptFileSafe *file = (ScriptFileSafe *) gen->GetObject(); - int delta = (int) gen->GetArgDWord(0); +void ScriptFile_MovePos_Generic(asIScriptGeneric *gen) +{ + ScriptFileSafe *file = (ScriptFileSafe*)gen->GetObject(); + int delta = (int)gen->GetArgDWord(0); + gen->SetReturnDWord(file->MovePos(delta)); } -void RegisterScriptFile_Native(asIScriptEngine *engine) { +void RegisterScriptFile_Native(asIScriptEngine *engine) +{ int r; r = engine->RegisterObjectType("file", 0, asOBJ_REF); @@ -243,7 +290,8 @@ void RegisterScriptFile_Native(asIScriptEngine *engine) { assert(r >= 0); } -void RegisterScriptFile_Generic(asIScriptEngine *engine) { +void RegisterScriptFile_Generic(asIScriptEngine *engine) +{ int r; r = engine->RegisterObjectType("file", 0, asOBJ_REF); @@ -318,33 +366,39 @@ void RegisterScriptFile_Generic(asIScriptEngine *engine) { assert(r >= 0); } -void RegisterScriptFile(asIScriptEngine *engine) { +void RegisterScriptFile(asIScriptEngine *engine) +{ if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) RegisterScriptFile_Generic(engine); else RegisterScriptFile_Native(engine); } -ScriptFileSafe::ScriptFileSafe() { - refCount = 1; - file = 0; +ScriptFileSafe::ScriptFileSafe() +{ + refCount = 1; + file = 0; mostSignificantByteFirst = false; } -ScriptFileSafe::~ScriptFileSafe() { +ScriptFileSafe::~ScriptFileSafe() +{ Close(); } -void ScriptFileSafe::AddRef() const { +void ScriptFileSafe::AddRef() const +{ ++refCount; } -void ScriptFileSafe::Release() const { +void ScriptFileSafe::Release() const +{ if (--refCount == 0) delete this; } -int ScriptFileSafe::Open(const std::string &filename, const std::string &mode) { +int ScriptFileSafe::Open(const std::string &filename, const std::string &mode) +{ // Close the previously opened file handle if (file) Close(); @@ -358,7 +412,7 @@ int ScriptFileSafe::Open(const std::string &filename, const std::string &mode) { #if AS_WRITE_OPS == 1 if (mode != "r" && mode != "w" && mode != "a") #else - if( mode != "r" ) + if (mode != "r") #endif return -2; else @@ -373,9 +427,10 @@ int ScriptFileSafe::Open(const std::string &filename, const std::string &mode) { if (myFilename.length() > 7 && myFilename.substr(myFilename.length() - 7, 7) == ".asdata") myFilename = myFilename.substr(0, myFilename.length() - 7); - // Replace all forbidden characters in the filename + // Replace all forbidden characters in the filename std::string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; - for (std::string::iterator it = myFilename.begin(); it < myFilename.end(); ++it) { + for (std::string::iterator it = myFilename.begin(); it < myFilename.end(); ++it) + { if (allowedChars.find(*it) == std::string::npos) *it = '_'; } @@ -393,7 +448,8 @@ int ScriptFileSafe::Open(const std::string &filename, const std::string &mode) { return 0; } -int ScriptFileSafe::Close() { +int ScriptFileSafe::Close() +{ if (file == 0) return -1; @@ -403,7 +459,8 @@ int ScriptFileSafe::Close() { return 0; } -int ScriptFileSafe::GetSize() const { +int ScriptFileSafe::GetSize() const +{ if (file == 0) return -1; @@ -415,14 +472,16 @@ int ScriptFileSafe::GetSize() const { return size; } -int ScriptFileSafe::GetPos() const { +int ScriptFileSafe::GetPos() const +{ if (file == 0) return -1; return ftell(file); } -int ScriptFileSafe::SetPos(int pos) { +int ScriptFileSafe::SetPos(int pos) +{ if (file == 0) return -1; @@ -432,7 +491,8 @@ int ScriptFileSafe::SetPos(int pos) { return r ? -1 : 0; } -int ScriptFileSafe::MovePos(int delta) { +int ScriptFileSafe::MovePos(int delta) +{ if (file == 0) return -1; @@ -442,19 +502,21 @@ int ScriptFileSafe::MovePos(int delta) { return r ? -1 : 0; } -int ScriptFileSafe::ReadString(unsigned int length, std::string &str) { +int ScriptFileSafe::ReadString(unsigned int length, std::string &str) +{ if (file == 0) return 0; // Read the string str.resize(length); - int size = (int) fread(&str[0], 1, length, file); + int size = (int)fread(&str[0], 1, length, file); str.resize(size); return size; } -int ScriptFileSafe::ReadLine(std::string &str) { +int ScriptFileSafe::ReadLine(std::string &str) +{ if (file == 0) return 0; @@ -462,7 +524,8 @@ int ScriptFileSafe::ReadLine(std::string &str) { str = ""; char buf[256]; - do { + do + { // Get the current position so we can determine how many characters were read int start = ftell(file); @@ -471,7 +534,8 @@ int ScriptFileSafe::ReadLine(std::string &str) { // Read the line (or first 255 characters, which ever comes first) char *r = fgets(buf, 256, file); - if (r == 0) break; + if (r == 0) + break; // Get the position after the read int end = ftell(file); @@ -483,107 +547,152 @@ int ScriptFileSafe::ReadLine(std::string &str) { return int(str.size()); } -asINT64 ScriptFileSafe::ReadInt(asUINT bytes) { +asINT64 ScriptFileSafe::ReadInt(asUINT bytes) +{ if (file == 0) return 0; - if (bytes > 8) bytes = 8; - if (bytes == 0) return 0; + if (bytes > 8) + bytes = 8; + if (bytes == 0) + return 0; unsigned char buf[8]; - size_t r = fread(buf, bytes, 1, file); - if (r == 0) return 0; + size_t r = fread(buf, bytes, 1, file); + if (r == 0) + return 0; asINT64 val = 0; - if (mostSignificantByteFirst) { + if (mostSignificantByteFirst) + { unsigned int n = 0; for (; n < bytes; n++) + { val |= asQWORD(buf[n]) << ((bytes - n - 1) * 8); + } if (buf[0] & 0x80) for (; n < 8; n++) + { val |= asQWORD(0xFF) << (n * 8); - } else { + } + } + else + { unsigned int n = 0; for (; n < bytes; n++) + { val |= asQWORD(buf[n]) << (n * 8); + } if (buf[0] & 0x80) for (; n < 8; n++) + { val |= asQWORD(0xFF) << (n * 8); + } } return val; } -asQWORD ScriptFileSafe::ReadUInt(asUINT bytes) { +asQWORD ScriptFileSafe::ReadUInt(asUINT bytes) +{ if (file == 0) return 0; - if (bytes > 8) bytes = 8; - if (bytes == 0) return 0; + if (bytes > 8) + bytes = 8; + if (bytes == 0) + return 0; unsigned char buf[8]; - size_t r = fread(buf, bytes, 1, file); - if (r == 0) return 0; + size_t r = fread(buf, bytes, 1, file); + if (r == 0) + return 0; asQWORD val = 0; - if (mostSignificantByteFirst) { + if (mostSignificantByteFirst) + { unsigned int n = 0; for (; n < bytes; n++) + { val |= asQWORD(buf[n]) << ((bytes - n - 1) * 8); - } else { + } + } + else + { unsigned int n = 0; for (; n < bytes; n++) + { val |= asQWORD(buf[n]) << (n * 8); + } } return val; } -float ScriptFileSafe::ReadFloat() { +float ScriptFileSafe::ReadFloat() +{ if (file == 0) return 0; unsigned char buf[4]; - size_t r = fread(buf, 4, 1, file); - if (r == 0) return 0; + size_t r = fread(buf, 4, 1, file); + if (r == 0) + return 0; asUINT val = 0; - if (mostSignificantByteFirst) { + if (mostSignificantByteFirst) + { unsigned int n = 0; for (; n < 4; n++) + { val |= asUINT(buf[n]) << ((3 - n) * 8); - } else { + } + } + else + { unsigned int n = 0; for (; n < 4; n++) + { val |= asUINT(buf[n]) << (n * 8); + } } return *reinterpret_cast(&val); } -double ScriptFileSafe::ReadDouble() { +double ScriptFileSafe::ReadDouble() +{ if (file == 0) return 0; unsigned char buf[8]; - size_t r = fread(buf, 8, 1, file); - if (r == 0) return 0; + size_t r = fread(buf, 8, 1, file); + if (r == 0) + return 0; asQWORD val = 0; - if (mostSignificantByteFirst) { + if (mostSignificantByteFirst) + { unsigned int n = 0; for (; n < 8; n++) + { val |= asQWORD(buf[n]) << ((7 - n) * 8); - } else { + } + } + else + { unsigned int n = 0; for (; n < 8; n++) + { val |= asQWORD(buf[n]) << (n * 8); + } } return *reinterpret_cast(&val); } -bool ScriptFileSafe::IsEOF() const { +bool ScriptFileSafe::IsEOF() const +{ if (file == 0) return true; @@ -592,7 +701,8 @@ bool ScriptFileSafe::IsEOF() const { #if AS_WRITE_OPS == 1 -int ScriptFileSafe::WriteString(const std::string &str) { +int ScriptFileSafe::WriteString(const std::string &str) +{ if (file == 0) return -1; @@ -602,71 +712,87 @@ int ScriptFileSafe::WriteString(const std::string &str) { return int(r); } -int ScriptFileSafe::WriteInt(asINT64 val, asUINT bytes) { +int ScriptFileSafe::WriteInt(asINT64 val, asUINT bytes) +{ if (file == 0) return 0; unsigned char buf[8]; - if (mostSignificantByteFirst) { + if (mostSignificantByteFirst) for (unsigned int n = 0; n < bytes; n++) + { buf[n] = (val >> ((bytes - n - 1) * 8)) & 0xFF; - } else { + } + else for (unsigned int n = 0; n < bytes; n++) + { buf[n] = (val >> (n * 8)) & 0xFF; - } + } size_t r = fwrite(&buf, bytes, 1, file); return int(r); } -int ScriptFileSafe::WriteUInt(asQWORD val, asUINT bytes) { +int ScriptFileSafe::WriteUInt(asQWORD val, asUINT bytes) +{ if (file == 0) return 0; unsigned char buf[8]; - if (mostSignificantByteFirst) { + if (mostSignificantByteFirst) for (unsigned int n = 0; n < bytes; n++) + { buf[n] = (val >> ((bytes - n - 1) * 8)) & 0xFF; - } else { + } + else for (unsigned int n = 0; n < bytes; n++) + { buf[n] = (val >> (n * 8)) & 0xFF; - } + } size_t r = fwrite(&buf, bytes, 1, file); return int(r); } -int ScriptFileSafe::WriteFloat(float f) { +int ScriptFileSafe::WriteFloat(float f) +{ if (file == 0) return 0; unsigned char buf[4]; - asUINT val = *reinterpret_cast(&f); - if (mostSignificantByteFirst) { + asUINT val = *reinterpret_cast(&f); + if (mostSignificantByteFirst) for (unsigned int n = 0; n < 4; n++) + { buf[n] = (val >> ((3 - n) * 4)) & 0xFF; - } else { + } + else for (unsigned int n = 0; n < 4; n++) + { buf[n] = (val >> (n * 8)) & 0xFF; - } + } size_t r = fwrite(&buf, 4, 1, file); return int(r); } -int ScriptFileSafe::WriteDouble(double d) { +int ScriptFileSafe::WriteDouble(double d) +{ if (file == 0) return 0; unsigned char buf[8]; - asQWORD val = *reinterpret_cast(&d); - if (mostSignificantByteFirst) { + asQWORD val = *reinterpret_cast(&d); + if (mostSignificantByteFirst) for (unsigned int n = 0; n < 8; n++) + { buf[n] = (val >> ((7 - n) * 8)) & 0xFF; - } else { + } + else for (unsigned int n = 0; n < 8; n++) + { buf[n] = (val >> (n * 8)) & 0xFF; - } + } size_t r = fwrite(&buf, 8, 1, file); return int(r); diff --git a/source/server/ScriptFileSafe.h b/source/server/ScriptFileSafe.h index 127bb3fa..944df6e8 100644 --- a/source/server/ScriptFileSafe.h +++ b/source/server/ScriptFileSafe.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ // copied from the angelscript library and edited for use in Rigs of Rods Multiplayer Server // 01 Jan 2012 @@ -43,7 +43,7 @@ along with Foobar. If not, see . // 1 = on #ifndef AS_WRITE_OPS -#define AS_WRITE_OPS 1 +#define AS_WRITE_OPS 1 #endif @@ -59,7 +59,8 @@ along with Foobar. If not, see . BEGIN_AS_NAMESPACE -class ScriptFileSafe { +class ScriptFileSafe +{ public: ScriptFileSafe(); @@ -117,7 +118,7 @@ class ScriptFileSafe { ~ScriptFileSafe(); mutable int refCount; - FILE *file; + FILE *file; }; // This function will determine the configuration of the engine diff --git a/source/server/broadcaster.cpp b/source/server/broadcaster.cpp index b9092714..dc705a9c 100644 --- a/source/server/broadcaster.cpp +++ b/source/server/broadcaster.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "broadcaster.h" @@ -27,24 +27,28 @@ along with Foobar. If not, see . #include -void *StartBroadcasterThread(void *data) { +void *StartBroadcasterThread(void *data) +{ Broadcaster *broadcaster = static_cast(data); + broadcaster->Thread(); return nullptr; } Broadcaster::Broadcaster(Sequencer *sequencer) : - m_sequencer(sequencer), - m_client_id(0), - m_socket(nullptr), - m_is_running(false), - m_is_dropping_packets(false) { + m_sequencer(sequencer), + m_client_id(0), + m_socket(nullptr), + m_is_running(false), + m_is_dropping_packets(false) +{ } -void Broadcaster::Start(int client_id, SWInetSocket *socket) { - m_client_id = client_id; - m_socket = socket; - m_is_running = true; +void Broadcaster::Start(int client_id, SWInetSocket *socket) +{ + m_client_id = client_id; + m_socket = socket; + m_is_running = true; m_is_dropping_packets = false; m_msg_queue.clear(); @@ -52,7 +56,8 @@ void Broadcaster::Start(int client_id, SWInetSocket *socket) { pthread_create(&m_thread, nullptr, StartBroadcasterThread, this); } -void Broadcaster::Stop() { +void Broadcaster::Stop() +{ m_queue_mutex.lock(); m_is_running = false; m_queue_cond.signal(); @@ -61,36 +66,41 @@ void Broadcaster::Stop() { pthread_join(m_thread, nullptr); } -void Broadcaster::Thread() { +void Broadcaster::Thread() +{ Logger::Log(LOG_DEBUG, "broadcaster m_thread %u owned by client_id %d", ThreadID::getID(), m_client_id); - while (m_is_running) { + while (m_is_running) + { queue_entry_t msg; // define a new scope and use a scope lock { MutexLocker scoped_lock(m_queue_mutex); - while (m_msg_queue.empty() && m_is_running) { + while (m_msg_queue.empty() && m_is_running) + { m_queue_mutex.wait(m_queue_cond); } - if (!m_is_running) { + if (!m_is_running) break; - } msg = m_msg_queue.front(); m_msg_queue.pop_front(); } - if (msg.is_dropping) { - Messaging::StatsAddOutgoingDrop(sizeof(RoRnet::Header) + msg.datalen); // Statistics - } else { - // TODO WARNING THE SOCKET IS NOT PROTECTED!!! - if (Messaging::SendMessage(m_socket, msg.type, msg.uid, msg.streamid, msg.datalen, msg.data) != 0) { - m_sequencer->disconnect(m_client_id, "Broadcaster: Send error", true, true); - break; - } + if (msg.is_dropping) + { + Messaging::StatsAddOutgoingDrop(sizeof(RoRnet::Header) + msg.datalen); // Statistics + } + else + // TODO WARNING THE SOCKET IS NOT PROTECTED!!! + if (Messaging::SendMessage(m_socket, msg.type, msg.uid, msg.streamid, msg.datalen, msg.data) != 0) + { + m_sequencer->disconnect(m_client_id, "Broadcaster: Send error", true, true); + break; } } - if (m_is_running) { + if (m_is_running) + { MutexLocker scoped_lock(m_queue_mutex); m_is_running = false; m_queue_mutex.wait(m_queue_cond); @@ -101,12 +111,13 @@ void Broadcaster::Thread() { //and keep in mind that it is called crazily and concurently from lots of threads //we MUST copy the data too //also, this function can be called by threads owning clients_mutex !!! -void Broadcaster::QueueMessage(int type, int uid, unsigned int streamid, unsigned int len, const char *data) { - if (!m_is_running) { +void Broadcaster::QueueMessage(int type, int uid, unsigned int streamid, unsigned int len, const char *data) +{ + if (!m_is_running) return; - } + // for now lets just queue msgs in the order received to make things simple - queue_entry_t msg = {false, type, uid, streamid, "", len}; + queue_entry_t msg = { false, type, uid, streamid, "", len }; memset(msg.data, 0, RORNET_MAX_MESSAGE_LENGTH); memcpy(msg.data, data, len); @@ -115,27 +126,32 @@ void Broadcaster::QueueMessage(int type, int uid, unsigned int streamid, unsigne // we will limit the entries in this queue // soft limit: we start dropping data packages - if ((m_msg_queue.size() > (size_t) QUEUE_SOFT_LIMIT) && (type == RoRnet::MSG2_STREAM_DATA)) { + if ((m_msg_queue.size() > (size_t)QUEUE_SOFT_LIMIT) && (type == RoRnet::MSG2_STREAM_DATA)) + { Logger::Log(LOG_DEBUG, "broadcaster queue soft full: m_thread %u owned by uid %d", ThreadID::getID(), m_client_id); - msg.is_dropping = true; + msg.is_dropping = true; m_is_dropping_packets = true; - } else if (m_msg_queue.size() < (size_t) QUEUE_SOFT_LIMIT - 20) // - 20 to prevent border problems + } + else if (m_msg_queue.size() < (size_t)QUEUE_SOFT_LIMIT - 20) // - 20 to prevent border problems { m_is_dropping_packets = false; + // hard limit drop anything, otherwise we would need to run through the queue and search and remove + // data packages, which is not really feasible } - - // hard limit drop anything, otherwise we would need to run through the queue and search and remove - // data packages, which is not really feasible - if (m_msg_queue.size() > (size_t) QUEUE_HARD_LIMIT) { + if (m_msg_queue.size() > (size_t)QUEUE_HARD_LIMIT) + { Logger::Log(LOG_DEBUG, "broadcaster queue hard full: m_thread %u owned by uid %d", ThreadID::getID(), m_client_id); msg.is_dropping = true; } - if (msg.is_dropping) { - Messaging::StatsAddOutgoingDrop(sizeof(RoRnet::Header) + msg.datalen); // Statistics - } else { + if (msg.is_dropping) + { + Messaging::StatsAddOutgoingDrop(sizeof(RoRnet::Header) + msg.datalen); // Statistics + } + else + { m_msg_queue.push_back(msg); //signal the thread that new data is waiting to be sent m_queue_cond.signal(); diff --git a/source/server/broadcaster.h b/source/server/broadcaster.h index 68948ea5..bcdb7b74 100644 --- a/source/server/broadcaster.h +++ b/source/server/broadcaster.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -30,18 +30,20 @@ class SWInetSocket; class Sequencer; -struct queue_entry_t { - bool is_dropping; - int type; - int uid; +struct queue_entry_t +{ + bool is_dropping; + int type; + int uid; unsigned int streamid; - char data[RORNET_MAX_MESSAGE_LENGTH]; + char data[RORNET_MAX_MESSAGE_LENGTH]; unsigned int datalen; }; void *StartBroadcasterThread(void *); -class Broadcaster { +class Broadcaster +{ friend void *StartBroadcasterThread(void *); public: @@ -57,19 +59,22 @@ class Broadcaster { void QueueMessage(int msg_type, int client_id, unsigned int streamid, unsigned int payload_len, const char *payload); - bool IsDroppingPackets() const { return m_is_dropping_packets; } + bool IsDroppingPackets() const + { + return m_is_dropping_packets; + } private: void Thread(); - Sequencer *m_sequencer; - pthread_t m_thread; - Mutex m_queue_mutex; - Condition m_queue_cond; - int m_client_id; - SWInetSocket *m_socket; - bool m_is_running; - bool m_is_dropping_packets; + Sequencer *m_sequencer; + pthread_t m_thread; + Mutex m_queue_mutex; + Condition m_queue_cond; + int m_client_id; + SWInetSocket *m_socket; + bool m_is_running; + bool m_is_dropping_packets; std::deque m_msg_queue; }; diff --git a/source/server/config.cpp b/source/server/config.cpp index 8e63fcd8..42558e1f 100644 --- a/source/server/config.cpp +++ b/source/server/config.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "config.h" @@ -36,30 +36,30 @@ along with Foobar. If not, see . #endif #ifdef _WIN32 -# define RESOURCE_DIR "" +# define RESOURCE_DIR "" #else // _WIN32 ~ trailing slash important -# define RESOURCE_DIR "/usr/share/rorserver/" +# define RESOURCE_DIR "/usr/share/rorserver/" #endif // _WIN32 -#define CONFIG_LINE_BUF_LEN 2000 +#define CONFIG_LINE_BUF_LEN 2000 // ============================== Variables =================================== -static std::string s_server_name; -static std::string s_terrain_name("any"); -static std::string s_public_password; -static std::string s_ip_addr("0.0.0.0"); -static std::string s_scriptname; -static std::string s_authfile("admins.txt"); -static std::string s_motdfile("motd.txt"); -static std::string s_rulesfile("rules.txt"); -static std::string s_owner; -static std::string s_website; -static std::string s_irc; -static std::string s_voip; -static std::string s_serverlist_host("multiplayer.rigsofrods.org"); -static std::string s_serverlist_path(""); -static std::string s_resourcedir(RESOURCE_DIR); +static std::string s_server_name; +static std::string s_terrain_name("any"); +static std::string s_public_password; +static std::string s_ip_addr("0.0.0.0"); +static std::string s_scriptname; +static std::string s_authfile("admins.txt"); +static std::string s_motdfile("motd.txt"); +static std::string s_rulesfile("rules.txt"); +static std::string s_owner; +static std::string s_website; +static std::string s_irc; +static std::string s_voip; +static std::string s_serverlist_host("multiplayer.rigsofrods.org"); +static std::string s_serverlist_path(""); +static std::string s_resourcedir(RESOURCE_DIR); static unsigned int s_max_vehicles(20); static unsigned int s_webserver_port(0); @@ -69,118 +69,133 @@ static unsigned int s_heartbeat_retry_count(5); static unsigned int s_heartbeat_retry_seconds(15); static unsigned int s_heartbeat_interval_sec(60); -static bool s_print_stats(false); -static bool s_webserver_enabled(false); -static bool s_foreground(false); -static bool s_show_version(false); -static bool s_show_help(false); +static bool s_print_stats(false); +static bool s_webserver_enabled(false); +static bool s_foreground(false); +static bool s_show_version(false); +static bool s_show_help(false); -static ServerType s_server_mode(SERVER_AUTO); +static ServerType s_server_mode(SERVER_AUTO); // ============================== Functions =================================== -namespace Config { - - void ShowHelp() { +namespace Config +{ + void ShowHelp() + { printf( - "Usage: rorserver [OPTIONS]\n" - "[OPTIONS] can be in Un*x `--help` or windows `/help` notation\n" - "\n" - " ~config-file (-c) Loads the configuration from a file\n" - " ~name Name of the server, no spaces, only\n" - " [a-z,0-9,A-Z]\n" - " ~terrain Map name (defaults to 'any')\n" - " ~max-clients|speed Maximum clients allowed\n" - " ~lan|inet Private or public server (defaults to inet)\n" - "\n" - " ~password Private server password\n" - " ~ip Public IP address to register with.\n" - " ~port Port to use (defaults to random 12000-12500)\n" - " ~verbosity {0-5} Sets displayed log verbosity\n" - " ~log-verbosity {0-5} Sets file log verbositylog verbosity\n" - " levels available to verbosity and logverbosity:\n" - " 0 = stack\n" - " 1 = debug\n" - " 2 = verbosity\n" - " 3 = info\n" - " 4 = warn\n" - " 5 = error\n" - " ~log-file Sets the filename of the log\n" - " ~script-file server script to execute\n" - " ~use-webserver enables the built-in webserver\n" - " ~webserver-port sets up the port for the webserver, default is game port + 100\n" - " ~version prints the server version numbers\n" - " ~fg starts the server in the foreground (background by default)\n" - " ~resource-dir sets the path to the resource directory\n" - " ~auth-file Sets the filename of the file that contains authorization info\n" - " ~motdf-ile Sets the filename of the file that contains the message of the day\n" - " ~rules-file Sets the filename of the file that contains rules for this server\n" - " ~vehicle-limit {0-...} Sets the maximum number of vehicles that a user is allowed to have\n" - " ~owner Sets the owner of this server (for the !owner command) (optional)\n" - " ~website Sets the website of this server (for the !website command) (optional)\n" - " ~irc Sets the IRC url for this server (for the !irc command) (optional)\n" - " ~voip Sets the voip url for this server (for the !voip command) (optional)\n" - " ~help Show this list\n"); - } - - void ShowVersion() { + "Usage: rorserver [OPTIONS]\n" + "[OPTIONS] can be in Un*x `--help` or windows `/help` notation\n" + "\n" + " ~config-file (-c) Loads the configuration from a file\n" + " ~name Name of the server, no spaces, only\n" + " [a-z,0-9,A-Z]\n" + " ~terrain Map name (defaults to 'any')\n" + " ~max-clients|speed Maximum clients allowed\n" + " ~lan|inet Private or public server (defaults to inet)\n" + "\n" + " ~password Private server password\n" + " ~ip Public IP address to register with.\n" + " ~port Port to use (defaults to random 12000-12500)\n" + " ~verbosity {0-5} Sets displayed log verbosity\n" + " ~log-verbosity {0-5} Sets file log verbositylog verbosity\n" + " levels available to verbosity and logverbosity:\n" + " 0 = stack\n" + " 1 = debug\n" + " 2 = verbosity\n" + " 3 = info\n" + " 4 = warn\n" + " 5 = error\n" + " ~log-file Sets the filename of the log\n" + " ~script-file server script to execute\n" + " ~use-webserver enables the built-in webserver\n" + " ~webserver-port sets up the port for the webserver, default is game port + 100\n" + " ~version prints the server version numbers\n" + " ~fg starts the server in the foreground (background by default)\n" + " ~resource-dir sets the path to the resource directory\n" + " ~auth-file Sets the filename of the file that contains authorization info\n" + " ~motdf-ile Sets the filename of the file that contains the message of the day\n" + " ~rules-file Sets the filename of the file that contains rules for this server\n" + " ~vehicle-limit {0-...} Sets the maximum number of vehicles that a user is allowed to have\n" + " ~owner Sets the owner of this server (for the !owner command) (optional)\n" + " ~website Sets the website of this server (for the !website command) (optional)\n" + " ~irc Sets the IRC url for this server (for the !irc command) (optional)\n" + " ~voip Sets the voip url for this server (for the !voip command) (optional)\n" + " ~help Show this list\n"); + } + + void ShowVersion() + { printf("Rigs of Rods Server\n"); printf(" * using Protocol %s\n", RORNET_VERSION); printf(" * built on %s, %s\n", __DATE__, __TIME__); #ifdef __GNUC__ printf(" * built with gcc %d.%d.%d\n", __GNUC_MINOR__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); -#endif //__GNUC__ +#endif //__GNUC__ } -//! runs a check that all the required fields are present - bool checkConfig() { - switch (getServerMode()) { - case SERVER_AUTO: - Logger::Log(LOG_INFO, "server started in automatic mode."); - break; - case SERVER_LAN: - Logger::Log(LOG_INFO, "server started in LAN mode."); - break; - case SERVER_INET: - Logger::Log(LOG_INFO, "server started in Internet mode."); - break; + //! runs a check that all the required fields are present + bool checkConfig() + { + switch (getServerMode()) + { + case SERVER_AUTO: + Logger::Log(LOG_INFO, "server started in automatic mode."); + break; + + case SERVER_LAN: + Logger::Log(LOG_INFO, "server started in LAN mode."); + break; + + case SERVER_INET: + Logger::Log(LOG_INFO, "server started in Internet mode."); + break; } - if (!getListenPort()) { + if (!getListenPort()) + { Logger::Log(LOG_WARN, "No port supplied, randomly generating one"); setListenPort(Utils::generateRandomPortNumber()); } - if (getWebserverEnabled() && !getWebserverPort()) { + if (getWebserverEnabled() && !getWebserverPort()) + { Logger::Log(LOG_WARN, "No Webserver port supplied, using listen port + 100: %d", getListenPort() + 100); setWebserverPort(getListenPort() + 100); } Logger::Log(LOG_INFO, "port: %d", getListenPort()); - if (getTerrainName().empty()) { + if (getTerrainName().empty()) + { Logger::Log(LOG_ERROR, "terrain not specified"); return 0; - } else + } + else + { Logger::Log(LOG_INFO, "terrain: %s", getTerrainName().c_str()); - - if (getMaxClients() < 2 || getMaxClients() > 64) { + } if (getMaxClients() < 2 || getMaxClients() > 64) + { Logger::Log(LOG_ERROR, "Max clients need to 2 or more, and 64 or less."); return 0; - } else + } + else + { Logger::Log(LOG_INFO, "maxclients: %d", getMaxClients()); - - if (getAuthFile().empty()) { + } if (getAuthFile().empty()) + { Logger::Log(LOG_ERROR, "Authorizations file not specified. Using default (admins.txt)"); setAuthFile("admins.txt"); } - if (getMOTDFile().empty()) { + if (getMOTDFile().empty()) + { Logger::Log(LOG_ERROR, "MOTD file not specified. Using default (motd.txt)."); setMOTDFile("motd.txt"); } - if (getMaxVehicles() < 1) { + if (getMaxVehicles() < 1) + { Logger::Log(LOG_ERROR, "The vehicle-limit cannot be less than 1!"); return 0; } @@ -192,46 +207,49 @@ namespace Config { !getTerrainName().empty(); } -#define HANDLE_ARG_VALUE(_NAME_, _BLOCK_) \ -{ \ - if(strcmp(arg, _NAME_) == 0) \ - { \ - if (pos + 1 < argc) \ - { \ - const char* value = argv[pos + 1]; \ - { _BLOCK_ } \ - pos += 2; \ - continue; \ - } \ - else \ - { \ - Logger::Log(LOG_WARN, \ - "Command line error: argument `%s` "\ - "at position %d has no value", \ - arg, pos); \ - return false; \ - } \ - } \ -} - -#define HANDLE_ARG_FLAG(_NAME_, _BLOCK_) \ -{ \ - if(strcmp(arg, _NAME_) == 0) \ - { \ - _BLOCK_ \ - pos += 1; \ - continue; \ - } \ -} - - bool ProcessArgs(int argc, char *argv[]) { +#define HANDLE_ARG_VALUE(_NAME_, _BLOCK_) \ + { \ + if (strcmp(arg, _NAME_) == 0) \ + { \ + if (pos + 1 < argc) \ + { \ + const char* value = argv[pos + 1]; \ + { _BLOCK_ } \ + pos += 2; \ + continue; \ + } \ + else \ + { \ + Logger::Log(LOG_WARN, \ + "Command line error: argument `%s` " \ + "at position %d has no value", \ + arg, pos); \ + return false; \ + } \ + } \ + } + +#define HANDLE_ARG_FLAG(_NAME_, _BLOCK_) \ + { \ + if (strcmp(arg, _NAME_) == 0) \ + { \ + _BLOCK_ \ + pos += 1; \ + continue; \ + } \ + } + + bool ProcessArgs(int argc, char *argv[]) + { #ifndef NOCMDLINE - int pos = 1; + int pos = 1; const char *config_file = nullptr; - while (pos < argc) { + while (pos < argc) + { // Cut off the leading `-`, `--` or `/` (windows) char *arg = argv[pos]; - if ((*arg != '-') && (*arg != '/')) { + if ((*arg != '-') && (*arg != '/')) + { Logger::Log(LOG_WARN, "Invalid command line argument `%s` at position %d", arg, pos); pos += 1; continue; @@ -259,123 +277,229 @@ namespace Config { HANDLE_ARG_VALUE("vehicle-limit", { setMaxVehicles(atoi(value)); }); HANDLE_ARG_VALUE("port", { setListenPort(atoi(value)); }); - HANDLE_ARG_FLAG ("print-stats", { setPrintStats(true); }); - HANDLE_ARG_FLAG ("use-webserver", { setWebserverEnabled(true); }); - HANDLE_ARG_FLAG ("foreground", { setForeground(true); }); - HANDLE_ARG_FLAG ("fg", { setForeground(true); }); - HANDLE_ARG_FLAG ("inet", { setServerMode(SERVER_INET); }); - HANDLE_ARG_FLAG ("lan", { setServerMode(SERVER_LAN); }); - HANDLE_ARG_FLAG ("version", { s_show_version = true; }); - HANDLE_ARG_FLAG ("help", { s_show_help = true; }); - HANDLE_ARG_FLAG ("h", { s_show_help = true; }); - HANDLE_ARG_FLAG ("?", { s_show_help = true; }); + HANDLE_ARG_FLAG("print-stats", { setPrintStats(true); }); + HANDLE_ARG_FLAG("use-webserver", { setWebserverEnabled(true); }); + HANDLE_ARG_FLAG("foreground", { setForeground(true); }); + HANDLE_ARG_FLAG("fg", { setForeground(true); }); + HANDLE_ARG_FLAG("inet", { setServerMode(SERVER_INET); }); + HANDLE_ARG_FLAG("lan", { setServerMode(SERVER_LAN); }); + HANDLE_ARG_FLAG("version", { s_show_version = true; }); + HANDLE_ARG_FLAG("help", { s_show_help = true; }); + HANDLE_ARG_FLAG("h", { s_show_help = true; }); + HANDLE_ARG_FLAG("?", { s_show_help = true; }); // Logging HANDLE_ARG_VALUE("log-file", { Logger::SetOutputFile(value); }); - HANDLE_ARG_VALUE("verbosity", { Logger::SetLogLevel(LOGTYPE_DISPLAY, (LogLevel) atoi(value)); }); - HANDLE_ARG_VALUE("log-verbosity", { Logger::SetLogLevel(LOGTYPE_FILE, (LogLevel) atoi(value)); }); + HANDLE_ARG_VALUE("verbosity", { Logger::SetLogLevel(LOGTYPE_DISPLAY, (LogLevel)atoi(value)); }); + HANDLE_ARG_VALUE("log-verbosity", { Logger::SetLogLevel(LOGTYPE_FILE, (LogLevel)atoi(value)); }); Logger::Log(LOG_WARN, "Unrecognized argument `%s` at position %d", arg, pos); pos += 1; } - if (config_file != nullptr) { + if (config_file != nullptr) LoadConfigFile(config_file); - } -#endif //NOCMDLINE +#endif //NOCMDLINE return true; } - bool isPublic() { return !getPublicPassword().empty(); } + bool isPublic() + { + return !getPublicPassword().empty(); + } - unsigned int getMaxClients() { return s_max_clients; } + unsigned int getMaxClients() + { + return s_max_clients; + } + + const std::string &getServerName() + { + return s_server_name; + } - const std::string &getServerName() { return s_server_name; } + const std::string &getTerrainName() + { + return s_terrain_name; + } - const std::string &getTerrainName() { return s_terrain_name; } + const std::string &getPublicPassword() + { + return s_public_password; + } - const std::string &getPublicPassword() { return s_public_password; } + const std::string &getIPAddr() + { + return s_ip_addr; + } - const std::string &getIPAddr() { return s_ip_addr; } + const std::string &getScriptName() + { + return s_scriptname; + } - const std::string &getScriptName() { return s_scriptname; } + bool getEnableScripting() + { + return s_scriptname != ""; + } - bool getEnableScripting() { return (s_scriptname != ""); } + unsigned int getListenPort() + { + return s_listen_port; + } - unsigned int getListenPort() { return s_listen_port; } + ServerType getServerMode() + { + return s_server_mode; + } - ServerType getServerMode() { return s_server_mode; } + bool getPrintStats() + { + return s_print_stats; + } - bool getPrintStats() { return s_print_stats; } + bool getWebserverEnabled() + { + return s_webserver_enabled; + } - bool getWebserverEnabled() { return s_webserver_enabled; } + unsigned int getWebserverPort() + { + return s_webserver_port; + } - unsigned int getWebserverPort() { return s_webserver_port; } + bool getForeground() + { + return s_foreground; + } - bool getForeground() { return s_foreground; } + const std::string &getResourceDir() + { + return s_resourcedir; + } - const std::string &getResourceDir() { return s_resourcedir; } + const std::string &getAuthFile() + { + return s_authfile; + } - const std::string &getAuthFile() { return s_authfile; } + const std::string &getMOTDFile() + { + return s_motdfile; + } - const std::string &getMOTDFile() { return s_motdfile; } + const std::string &getRulesFile() + { + return s_rulesfile; + } - const std::string &getRulesFile() { return s_rulesfile; } + unsigned int getMaxVehicles() + { + return s_max_vehicles; + } - unsigned int getMaxVehicles() { return s_max_vehicles; } + const std::string &getOwner() + { + return s_owner; + } - const std::string &getOwner() { return s_owner; } + const std::string &getWebsite() + { + return s_website; + } - const std::string &getWebsite() { return s_website; } + const std::string &getIRC() + { + return s_irc; + } - const std::string &getIRC() { return s_irc; } + const std::string &getVoIP() + { + return s_voip; + } - const std::string &getVoIP() { return s_voip; } + const std::string &GetServerlistHost() + { + return s_serverlist_host; + } - const std::string &GetServerlistHost() { return s_serverlist_host; } + const char *GetServerlistHostC() + { + return s_serverlist_host.c_str(); + } - const char *GetServerlistHostC() { return s_serverlist_host.c_str(); } + const std::string &GetServerlistPath() + { + return s_serverlist_path; + } - const std::string &GetServerlistPath() { return s_serverlist_path; } + bool GetShowVersion() + { + return s_show_version; + } - bool GetShowVersion() { return s_show_version; } + bool GetShowHelp() + { + return s_show_help; + } - bool GetShowHelp() { return s_show_help; } + unsigned int GetHeartbeatRetryCount() + { + return s_heartbeat_retry_count; + } - unsigned int GetHeartbeatRetryCount() { return s_heartbeat_retry_count; } + unsigned int GetHeartbeatRetrySeconds() + { + return s_heartbeat_retry_seconds; + } - unsigned int GetHeartbeatRetrySeconds() { return s_heartbeat_retry_seconds; } + unsigned int GetHeartbeatIntervalSec() + { + return s_heartbeat_interval_sec; + } - unsigned int GetHeartbeatIntervalSec() { return s_heartbeat_interval_sec; } + bool setScriptName(const std::string &name) + { + if (name.empty()) + return false; - bool setScriptName(const std::string &name) { - if (name.empty()) return false; s_scriptname = name; return true; } - bool setMaxClients(unsigned int num) { - if (num < 2 || num > 64) return false; + bool setMaxClients(unsigned int num) + { + if (num < 2 || num > 64) + return false; + s_max_clients = num; return true; } - bool setServerName(const std::string &name) { - if (name.empty()) return false; + bool setServerName(const std::string &name) + { + if (name.empty()) + return false; + s_server_name = name; return true; } - bool setTerrain(const std::string &tern) { - if (tern.empty()) return false; + bool setTerrain(const std::string &tern) + { + if (tern.empty()) + return false; + s_terrain_name = tern; return true; } - bool setPublicPass(const std::string &pub_pass) { + bool setPublicPass(const std::string &pub_pass) + { if (pub_pass.length() > 0 && pub_pass.size() < 250 && - !SHA1FromString(s_public_password, pub_pass)) { + !SHA1FromString(s_public_password, pub_pass)) + { Logger::Log(LOG_ERROR, "could not generate server SHA1 password hash!"); s_public_password = ""; return false; @@ -385,167 +509,244 @@ namespace Config { return true; } - bool setIPAddr(const std::string &ip) { - if (ip.empty()) return false; + bool setIPAddr(const std::string &ip) + { + if (ip.empty()) + return false; + s_ip_addr = ip; return true; } - bool setListenPort(unsigned int port) { + bool setListenPort(unsigned int port) + { s_listen_port = port; return true; } - void setWebserverPort(unsigned int port) { s_webserver_port = port; } + void setWebserverPort(unsigned int port) + { + s_webserver_port = port; + } - void setWebserverEnabled(bool webserver) { s_webserver_enabled = webserver; } + void setWebserverEnabled(bool webserver) + { + s_webserver_enabled = webserver; + } - void setPrintStats(bool value) { s_print_stats = value; } + void setPrintStats(bool value) + { + s_print_stats = value; + } - void setAuthFile(const std::string &file) { s_authfile = file; } + void setAuthFile(const std::string &file) + { + s_authfile = file; + } - void setMOTDFile(const std::string &file) { s_motdfile = file; } + void setMOTDFile(const std::string &file) + { + s_motdfile = file; + } - void setRulesFile(const std::string &file) { s_rulesfile = file; } + void setRulesFile(const std::string &file) + { + s_rulesfile = file; + } - void setMaxVehicles(unsigned int num) { s_max_vehicles = num; } + void setMaxVehicles(unsigned int num) + { + s_max_vehicles = num; + } - void setOwner(const std::string &owner) { s_owner = owner; } + void setOwner(const std::string &owner) + { + s_owner = owner; + } - void setForeground(bool value) { s_foreground = value; } + void setForeground(bool value) + { + s_foreground = value; + } - void setWebsite(const std::string &website) { s_website = website; } + void setWebsite(const std::string &website) + { + s_website = website; + } - void setIRC(const std::string &irc) { s_irc = irc; } + void setIRC(const std::string &irc) + { + s_irc = irc; + } - void setVoIP(const std::string &voip) { s_voip = voip; } + void setVoIP(const std::string &voip) + { + s_voip = voip; + } - void setHeartbeatIntervalSec(unsigned sec) { + void setHeartbeatIntervalSec(unsigned sec) + { s_heartbeat_interval_sec = sec; Logger::Log(LOG_VERBOSE, "Hearbeat interval is %d seconds", sec); } - bool setServerMode(ServerType mode) { + bool setServerMode(ServerType mode) + { s_server_mode = mode; return true; } - void setResourceDir(std::string dir) { + void setResourceDir(std::string dir) + { if (dir.length() > 0 && dir.substr(dir.length() - 1) != "/") dir += "/"; s_resourcedir = dir; } - inline void SetConfServerMode(std::string const &val) { + inline void SetConfServerMode(std::string const &val) + { if (val.compare("inet") == 0) setServerMode(SERVER_INET); else setServerMode(SERVER_LAN); } -// Cloned from RudeConfig (http://rudeserver.com/config/) we used before. #compatibility - inline bool RudeStrToBool(const char *val) { - switch (val[0]) { - case 't': - case 'T': - case 'y': - case 'Y': - case '1': - return true; - case 'o': - case 'O': - return (val[1] == 'n' || val[1] == 'N'); - default: - return false; + // Cloned from RudeConfig (http://rudeserver.com/config/) we used before. #compatibility + inline bool RudeStrToBool(const char *val) + { + switch (val[0]) + { + case 't': + case 'T': + case 'y': + case 'Y': + case '1': + return true; + + case 'o': + case 'O': + return val[1] == 'n' || val[1] == 'N'; + + default: + return false; } } -#define VAL_STR(_STR_) (Str::SanitizeUtf8(_STR_)) -#define VAL_INT(_STR_) (atoi(value)) // Cloned from RudeConfig we used before. #compatibility -#define VAL_BOOL(_STR_)(RudeStrToBool(value)) - - void ProcessConfigEntry(const char *key, const char *value) { - if (strcmp(key, "baseconfig") == 0) { LoadConfigFile(VAL_STR (value)); } - else if (strcmp(key, "slots") == 0) { setMaxClients(VAL_INT (value)); } - else if (strcmp(key, "name") == 0) { setServerName(VAL_STR (value)); } - else if (strcmp(key, "scriptname") == 0) { setScriptName(VAL_STR (value)); } - else if (strcmp(key, "terrain") == 0) { setTerrain(VAL_STR (value)); } - else if (strcmp(key, "password") == 0) { setPublicPass(VAL_STR (value)); } - else if (strcmp(key, "ip") == 0) { setIPAddr(VAL_STR (value)); } - else if (strcmp(key, "port") == 0) { setListenPort(VAL_INT (value)); } - else if (strcmp(key, "mode") == 0) { SetConfServerMode(VAL_STR (value)); } - else if (strcmp(key, "printstats") == 0) { setPrintStats(VAL_BOOL(value)); } - else if (strcmp(key, "webserver") == 0) { setWebserverEnabled(VAL_BOOL(value)); } - else if (strcmp(key, "webserverport") == 0) { setWebserverPort(VAL_INT (value)); } - else if (strcmp(key, "foreground") == 0) { setForeground(VAL_BOOL(value)); } - else if (strcmp(key, "resdir") == 0) { setResourceDir(VAL_STR (value)); } - else if (strcmp(key, "logfilename") == 0) { Logger::SetOutputFile(VAL_STR (value)); } - else if (strcmp(key, "authfile") == 0) { setAuthFile(VAL_STR (value)); } - else if (strcmp(key, "motdfile") == 0) { setMOTDFile(VAL_STR (value)); } - else if (strcmp(key, "rulesfile") == 0) { setRulesFile(VAL_STR (value)); } - else if (strcmp(key, "vehiclelimit") == 0) { setMaxVehicles(VAL_INT (value)); } - else if (strcmp(key, "owner") == 0) { setOwner(VAL_STR (value)); } - else if (strcmp(key, "website") == 0) { setWebsite(VAL_STR (value)); } - else if (strcmp(key, "irc") == 0) { setIRC(VAL_STR (value)); } - else if (strcmp(key, "voip") == 0) { setVoIP(VAL_STR (value)); } - else if (strcmp(key, "serverlist-host") == 0) { s_serverlist_host = VAL_STR (value); } - else if (strcmp(key, "serverlist-path") == 0) { s_serverlist_path = VAL_STR (value); } - else if (strcmp(key, "verbosity") == 0) { Logger::SetLogLevel(LOGTYPE_DISPLAY, (LogLevel) VAL_INT(value)); } - else if (strcmp(key, "logverbosity") == 0) { Logger::SetLogLevel(LOGTYPE_FILE, (LogLevel) VAL_INT(value)); } - else if (strcmp(key, "heartbeat-interval") == 0) { setHeartbeatIntervalSec(VAL_INT(value)); } - else { +#define VAL_STR(_STR_) (Str::SanitizeUtf8(_STR_)) +#define VAL_INT(_STR_) (atoi(value)) // Cloned from RudeConfig we used before. #compatibility +#define VAL_BOOL(_STR_) (RudeStrToBool(value)) + + void ProcessConfigEntry(const char *key, const char *value) + { + if (strcmp(key, "baseconfig") == 0) + LoadConfigFile(VAL_STR(value)); + else if (strcmp(key, "slots") == 0) + setMaxClients(VAL_INT(value)); + else if (strcmp(key, "name") == 0) + setServerName(VAL_STR(value)); + else if (strcmp(key, "scriptname") == 0) + setScriptName(VAL_STR(value)); + else if (strcmp(key, "terrain") == 0) + setTerrain(VAL_STR(value)); + else if (strcmp(key, "password") == 0) + setPublicPass(VAL_STR(value)); + else if (strcmp(key, "ip") == 0) + setIPAddr(VAL_STR(value)); + else if (strcmp(key, "port") == 0) + setListenPort(VAL_INT(value)); + else if (strcmp(key, "mode") == 0) + SetConfServerMode(VAL_STR(value)); + else if (strcmp(key, "printstats") == 0) + setPrintStats(VAL_BOOL(value)); + else if (strcmp(key, "webserver") == 0) + setWebserverEnabled(VAL_BOOL(value)); + else if (strcmp(key, "webserverport") == 0) + setWebserverPort(VAL_INT(value)); + else if (strcmp(key, "foreground") == 0) + setForeground(VAL_BOOL(value)); + else if (strcmp(key, "resdir") == 0) + setResourceDir(VAL_STR(value)); + else if (strcmp(key, "logfilename") == 0) + Logger::SetOutputFile(VAL_STR(value)); + else if (strcmp(key, "authfile") == 0) + setAuthFile(VAL_STR(value)); + else if (strcmp(key, "motdfile") == 0) + setMOTDFile(VAL_STR(value)); + else if (strcmp(key, "rulesfile") == 0) + setRulesFile(VAL_STR(value)); + else if (strcmp(key, "vehiclelimit") == 0) + setMaxVehicles(VAL_INT(value)); + else if (strcmp(key, "owner") == 0) + setOwner(VAL_STR(value)); + else if (strcmp(key, "website") == 0) + setWebsite(VAL_STR(value)); + else if (strcmp(key, "irc") == 0) + setIRC(VAL_STR(value)); + else if (strcmp(key, "voip") == 0) + setVoIP(VAL_STR(value)); + else if (strcmp(key, "serverlist-host") == 0) + s_serverlist_host = VAL_STR(value); + else if (strcmp(key, "serverlist-path") == 0) + s_serverlist_path = VAL_STR(value); + else if (strcmp(key, "verbosity") == 0) + Logger::SetLogLevel(LOGTYPE_DISPLAY, (LogLevel)VAL_INT(value)); + else if (strcmp(key, "logverbosity") == 0) + Logger::SetLogLevel(LOGTYPE_FILE, (LogLevel)VAL_INT(value)); + else if (strcmp(key, "heartbeat-interval") == 0) + setHeartbeatIntervalSec(VAL_INT(value)); + else Logger::Log(LOG_WARN, "Unknown key '%s' (value: '%s') in config file.", key, value); - } } - void LoadConfigFile(const std::string &filename) { + void LoadConfigFile(const std::string &filename) + { Logger::Log(LOG_INFO, "loading config file %s ...", filename.c_str()); FILE *f = fopen(filename.c_str(), "r"); - if (f == nullptr) { + if (f == nullptr) + { Logger::Log(LOG_ERROR, "Failed to open config file %s ...", filename.c_str()); return; } size_t line_num = 0; - while (!feof(f) && !ferror(f)) { + while (!feof(f) && !ferror(f)) + { ++line_num; char line_buf[CONFIG_LINE_BUF_LEN]; - if (fgets(line_buf, CONFIG_LINE_BUF_LEN, f) == nullptr) { + if (fgets(line_buf, CONFIG_LINE_BUF_LEN, f) == nullptr) break; - } char *key_start = line_buf; - char *val_end = line_buf + strlen(line_buf); - Str::TrimAscii(key_start, val_end); // In-out + char *val_end = line_buf + strlen(line_buf); + Str::TrimAscii(key_start, val_end); // In-out if (key_start == val_end) - continue; // Skip empty lines + continue; // Skip empty lines if (*key_start == '#') - continue; // Skip comment lines + continue; // Skip comment lines char *key_end = strrchr(key_start, '='); - if (key_end == nullptr) { + if (key_end == nullptr) + { Logger::Log(LOG_ERROR, "Invalid line %u; missing '=' separator (config file %s)", line_num, filename.c_str()); - continue; // Skip invalid line + continue; // Skip invalid line } char *val_start = key_end + 1; - Str::TrimAscii(key_start, key_end); // In-out + Str::TrimAscii(key_start, key_end); // In-out Str::TrimAscii(val_start, val_end); *key_end = '\0'; *val_end = '\0'; ProcessConfigEntry(key_start, val_start); } - if (!feof(f)) { + if (!feof(f)) Logger::Log(LOG_ERROR, "Error reading line %u from config file %s", line_num, filename.c_str()); - } fclose(f); } - } //namespace Config diff --git a/source/server/config.h b/source/server/config.h index 424b2ea4..5d562c92 100644 --- a/source/server/config.h +++ b/source/server/config.h @@ -1,37 +1,38 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once #include "UnicodeStrings.h" // server modes -enum ServerType { +enum ServerType +{ SERVER_LAN = 0, SERVER_INET, SERVER_AUTO }; -namespace Config { - -//! runs a check that all the required fields are present +namespace Config +{ + //! runs a check that all the required fields are present bool checkConfig(); bool ProcessArgs(int argc, char *argv[]); @@ -40,11 +41,11 @@ namespace Config { void ShowVersion(); -//! checks if a password has been set for server access + //! checks if a password has been set for server access bool isPublic(); -//! getter function -//!@{ + //! getter function + //!@{ unsigned int getMaxClients(); const std::string &getServerName(); @@ -104,10 +105,10 @@ namespace Config { bool GetShowHelp(); bool GetShowVersion(); -//!@} + //!@} -//! setter functions -//!@{ + //! setter functions + //!@{ bool setMaxClients(unsigned int num); bool setServerName(const std::string &name); @@ -153,7 +154,6 @@ namespace Config { void setIRC(const std::string &irc); void setVoIP(const std::string &voip); -//!@} - + //!@} } // namespace Config diff --git a/source/server/http.cpp b/source/server/http.cpp index ab981d49..d067e1f0 100644 --- a/source/server/http.cpp +++ b/source/server/http.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "http.h" @@ -31,34 +31,36 @@ along with Foobar. If not, see . #include #include -namespace Http { - - const char *METHOD_GET = "GET"; - const char *METHOD_POST = "POST"; - const char *METHOD_PUT = "PUT"; +namespace Http +{ + const char *METHOD_GET = "GET"; + const char *METHOD_POST = "POST"; + const char *METHOD_PUT = "PUT"; const char *METHOD_DELETE = "DELETE"; bool RequestRaw( - const char *method, - const char *host, - const char *url, - const char *content_type, - const char *payload, - char *out_response_buffer, - unsigned response_buf_len) { + const char *method, + const char *host, + const char *url, + const char *content_type, + const char *payload, + char *out_response_buffer, + unsigned response_buf_len) + { method = (method == nullptr) ? METHOD_GET : method; - SWInetSocket socket; + SWInetSocket socket; SWInetSocket::SWBaseError result; - if (!socket.connect(80, host, &result) || (result != SWInetSocket::ok)) { + if (!socket.connect(80, host, &result) || (result != SWInetSocket::ok)) + { Logger::Log(LOG_ERROR, "Could not process HTTP %s request %s%s failed, error: ", method, host, url, result.get_error().c_str()); return false; } - char query[2000] = {0}; - char *query_pos = query; + char query[2000] = { 0 }; + char *query_pos = query; query_pos += sprintf(query_pos, "%s %s HTTP/1.1" "\r\n", method, url); query_pos += sprintf(query_pos, "Host: %s" "\r\n", host); @@ -68,7 +70,8 @@ namespace Http { sprintf(query_pos, "\r\n%s", payload); - if (socket.sendmsg(query, &result) < 0) { + if (socket.sendmsg(query, &result) < 0) + { Logger::Log(LOG_ERROR, "Could not process HTTP %s request %s%s failed, error: ", method, host, url, result.get_error().c_str()); @@ -76,7 +79,8 @@ namespace Http { } int response_len = socket.recv(out_response_buffer, response_buf_len, &result); - if (response_len < 0) { + if (response_len < 0) + { Logger::Log(LOG_ERROR, "Could not process HTTP %s request %s%s failed, invalid response length, error message: ", method, host, url, result.get_error().c_str()); @@ -88,50 +92,56 @@ namespace Http { } int Request( - const char *method, - const char *host, - const char *url, - const char *content_type, - const char *payload, - Response *response) { + const char *method, + const char *host, + const char *url, + const char *content_type, + const char *payload, + Response *response) + { assert(response != nullptr); - char response_buf[5000] = {0}; - if (!RequestRaw(method, host, url, content_type, payload, response_buf, 5000)) { + char response_buf[5000] = { 0 }; + if (!RequestRaw(method, host, url, content_type, payload, response_buf, 5000)) return -1; - } + std::string response_str(response_buf); - if (!response->FromBuffer(response_str)) { + if (!response->FromBuffer(response_str)) return -2; - } + return response->GetCode(); } Response::Response() : - m_response_code(0) { + m_response_code(0) + { } - const std::string &Response::GetBody() { + const std::string &Response::GetBody() + { return m_headermap["body"]; } - const std::vector Response::GetBodyLines() { + const std::vector Response::GetBodyLines() + { std::vector lines; strict_tokenize(m_headermap["body"], lines, "\n"); return lines; } - bool Response::IsChunked() { + bool Response::IsChunked() + { return "chunked" == m_headermap["Transfer-Encoding"]; } - bool Response::FromBuffer(const std::string &message) { + bool Response::FromBuffer(const std::string &message) + { m_response_code = -1; m_headermap.clear(); - std::size_t locHolder; + std::size_t locHolder; locHolder = message.find("\r\n\r\n"); std::vector header; std::vector tmp; @@ -143,37 +153,37 @@ namespace Http { strcpy(line, header[0].c_str()); char *tok0 = std::strtok(line, " "); char *tok1 = std::strtok(nullptr, " "); - if (tok0 == nullptr || tok1 == nullptr) { + if (tok0 == nullptr || tok1 == nullptr) + { Logger::Log(LOG_ERROR, "Internal: HTTP response has malformed 1st line: \n%s", header[0].c_str()); return false; } m_response_code = atoi(tok1); // Process header lines - for (unsigned short index = 1; index < header.size(); index++) { + for (unsigned short index = 1; index < header.size(); index++) + { tmp.clear(); tokenize(header[index], tmp, ":"); - if (tmp.size() != 2) { + if (tmp.size() != 2) continue; - } m_headermap[trim(tmp[0])] = trim(tmp[1]); } tmp.clear(); locHolder = message.find_first_not_of("\r\n", locHolder); - if (std::string::npos == locHolder) { + if (std::string::npos == locHolder) + { Logger::Log(LOG_ERROR, "Internal: HTTP message does not appear to contain a body: \n%s", message.c_str()); return false; } strict_tokenize(message.substr(locHolder), tmp, "\r\n"); - if (IsChunked()) { + if (IsChunked()) m_headermap["body"] = tmp[1]; - } else { + else m_headermap["body"] = tmp[0]; - } return true; } - } // namespace Http diff --git a/source/server/http.h b/source/server/http.h index c93f31d9..ce80175b 100644 --- a/source/server/http.h +++ b/source/server/http.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -24,15 +24,16 @@ along with Foobar. If not, see . #include #include -namespace Http { - +namespace Http +{ extern const char *METHOD_GET; extern const char *METHOD_POST; extern const char *METHOD_PUT; extern const char *METHOD_DELETE; - class Response { - public: + class Response + { +public: Response(); const std::string &GetBody(); @@ -43,29 +44,31 @@ namespace Http { bool FromBuffer(const std::string &message); - int GetCode() { return m_response_code; } + int GetCode() + { + return m_response_code; + } - private: +private: std::map m_headermap; - int m_response_code; + int m_response_code; }; bool RequestRaw( - const char *method, - const char *host, - const char *url, - const char *content_type, - const char *payload, - char *out_response_buffer, - unsigned response_buf_len); + const char *method, + const char *host, + const char *url, + const char *content_type, + const char *payload, + char *out_response_buffer, + unsigned response_buf_len); int Request( - const char *method, - const char *host, - const char *url, - const char *content_type, - const char *payload, - Response *out_response); - + const char *method, + const char *host, + const char *url, + const char *content_type, + const char *payload, + Response *out_response); } // namespace Http diff --git a/source/server/listener.cpp b/source/server/listener.cpp index e39c6a5f..c54005f8 100644 --- a/source/server/listener.cpp +++ b/source/server/listener.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "listener.h" @@ -39,33 +39,38 @@ along with Foobar. If not, see . #endif -void *s_lsthreadstart(void *arg) { +void *s_lsthreadstart(void *arg) +{ Listener *listener = static_cast(arg); + listener->threadstart(); return nullptr; } Listener::Listener(Sequencer *sequencer, int port) : - m_listen_port(port), - m_sequencer(sequencer), - m_thread_shutdown(false) { + m_listen_port(port), + m_sequencer(sequencer), + m_thread_shutdown(false) +{ } -Listener::~Listener(void) { - if (!m_thread_shutdown) { +Listener::~Listener(void) +{ + if (!m_thread_shutdown) this->Shutdown(); - } } -bool Listener::Initialize() { - if (!m_ready_cond.Initialize()) { +bool Listener::Initialize() +{ + if (!m_ready_cond.Initialize()) return false; - } - return (0 == pthread_create(&m_thread, NULL, s_lsthreadstart, this)); + + return 0 == pthread_create(&m_thread, NULL, s_lsthreadstart, this); } -void Listener::Shutdown() { +void Listener::Shutdown() +{ Logger::Log(LOG_VERBOSE, "Stopping listener thread..."); m_thread_shutdown = true; m_listen_socket.disconnect(); @@ -73,27 +78,33 @@ void Listener::Shutdown() { Logger::Log(LOG_VERBOSE, "Listener thread stopped"); } -bool Listener::WaitUntilReady() { +bool Listener::WaitUntilReady() +{ int result = 0; - if (!m_ready_cond.Wait(&result)) { + + if (!m_ready_cond.Wait(&result)) + { Logger::Log(LOG_ERROR, "Internal: Error while starting listener thread"); return false; } - if (result < 0) { + if (result < 0) + { Logger::Log(LOG_ERROR, "Internal: Listerer thread failed to start"); return false; } return true; } -void Listener::threadstart() { +void Listener::threadstart() +{ Logger::Log(LOG_DEBUG, "Listerer thread starting"); //here we start SWBaseSocket::SWBaseError error; //manage the listening socket m_listen_socket.bind(m_listen_port, &error); - if (error != SWBaseSocket::ok) { + if (error != SWBaseSocket::ok) + { //this is an error! Logger::Log(LOG_ERROR, "FATAL Listerer: %s", error.get_error().c_str()); //there is nothing we can do here @@ -106,16 +117,17 @@ void Listener::threadstart() { m_ready_cond.Signal(1); //await connections - while (!m_thread_shutdown) { + while (!m_thread_shutdown) + { Logger::Log(LOG_VERBOSE, "Listener awaiting connections"); - SWInetSocket *ts = (SWInetSocket *) m_listen_socket.accept(&error); + SWInetSocket *ts = (SWInetSocket*)m_listen_socket.accept(&error); - if (error != SWBaseSocket::ok) { - if (m_thread_shutdown) { + if (error != SWBaseSocket::ok) + { + if (m_thread_shutdown) Logger::Log(LOG_ERROR, "INFO Listener shutting down"); - } else { + else Logger::Log(LOG_ERROR, "ERROR Listener: %s", error.get_error().c_str()); - } } @@ -125,11 +137,11 @@ void Listener::threadstart() { #endif //receive a magic - int type; - int source; + int type; + int source; unsigned int len; unsigned int streamid; - char buffer[4096]; + char buffer[4096]; try { // this is the start of it all, it all starts with a simple hello @@ -137,20 +149,21 @@ void Listener::threadstart() { throw std::runtime_error("ERROR Listener: receiving first message"); // make sure our first message is a hello message - if (type != RoRnet::MSG2_HELLO) { + if (type != RoRnet::MSG2_HELLO) + { Messaging::SendMessage(ts, RoRnet::MSG2_WRONG_VER, 0, 0, 0, 0); throw std::runtime_error("ERROR Listener: protocol error"); } // check client version - if (source == 5000 && (std::string(buffer) == "MasterServer")) { + if (source == 5000 && (std::string(buffer) == "MasterServer")) + { Logger::Log(LOG_VERBOSE, "Master Server knocked ..."); // send back some information, then close socket char tmp[2048] = ""; sprintf(tmp, "protocol:%s\nrev:%s\nbuild_on:%s_%s\n", RORNET_VERSION, VERSION, __DATE__, __TIME__); - if (Messaging::SendMessage(ts, RoRnet::MSG2_MASTERINFO, 0, 0, (unsigned int) strlen(tmp), tmp)) { + if (Messaging::SendMessage(ts, RoRnet::MSG2_MASTERINFO, 0, 0, (unsigned int)strlen(tmp), tmp)) throw std::runtime_error("ERROR Listener: sending master info"); - } // close socket ts->disconnect(&error); delete ts; @@ -158,7 +171,8 @@ void Listener::threadstart() { } // compare the versions if they are compatible - if (strncmp(buffer, RORNET_VERSION, strlen(RORNET_VERSION))) { + if (strncmp(buffer, RORNET_VERSION, strlen(RORNET_VERSION))) + { // not compatible Messaging::SendMessage(ts, RoRnet::MSG2_WRONG_VER, 0, 0, 0, 0); throw std::runtime_error("ERROR Listener: bad version: " + std::string(buffer) + ". rejecting ..."); @@ -168,10 +182,12 @@ void Listener::threadstart() { std::string motd_str; { std::vector lines; - int res = Utils::ReadLinesFromFile(Config::getMOTDFile(), lines); + int res = Utils::ReadLinesFromFile(Config::getMOTDFile(), lines); if (!res) for (std::vector::iterator it = lines.begin(); it != lines.end(); it++) + { motd_str += *it + "\n"; + } } Logger::Log(LOG_DEBUG, "Listener sending server settings"); @@ -183,12 +199,13 @@ void Listener::threadstart() { strncpy(settings.servername, Config::getServerName().c_str(), Config::getServerName().size()); strncpy(settings.terrain, Config::getTerrainName().c_str(), Config::getTerrainName().size()); - if (Messaging::SendMessage(ts, RoRnet::MSG2_HELLO, 0, 0, (unsigned int) sizeof(RoRnet::ServerInfo), - (char *) &settings)) + if (Messaging::SendMessage(ts, RoRnet::MSG2_HELLO, 0, 0, (unsigned int)sizeof(RoRnet::ServerInfo), + (char*)&settings)) throw std::runtime_error("ERROR Listener: sending version"); //receive user infos - if (Messaging::ReceiveMessage(ts, &type, &source, &streamid, &len, buffer, 256)) { + if (Messaging::ReceiveMessage(ts, &type, &source, &streamid, &len, buffer, 256)) + { std::stringstream error_msg; error_msg << "ERROR Listener: receiving user infos\n" << "ERROR Listener: got that: " @@ -203,7 +220,7 @@ void Listener::threadstart() { throw std::runtime_error("Error: did not receive proper user credentials"); Logger::Log(LOG_INFO, "Listener creating a new client..."); - RoRnet::UserInfo *user = (RoRnet::UserInfo *) buffer; + RoRnet::UserInfo *user = (RoRnet::UserInfo*)buffer; user->authstatus = RoRnet::AUTH_NONE; // authenticate @@ -211,23 +228,25 @@ void Listener::threadstart() { user->authstatus = m_sequencer->AuthorizeNick(std::string(user->usertoken), nickname); strncpy(user->username, nickname.c_str(), RORNET_MAX_USERNAME_LEN); - if (Config::isPublic()) { + if (Config::isPublic()) + { Logger::Log(LOG_DEBUG, "password login: %s == %s?", Config::getPublicPassword().c_str(), user->serverpassword); - if (strncmp(Config::getPublicPassword().c_str(), user->serverpassword, 40)) { + if (strncmp(Config::getPublicPassword().c_str(), user->serverpassword, 40)) + { Messaging::SendMessage(ts, RoRnet::MSG2_WRONG_PW, 0, 0, 0, 0); throw std::runtime_error("ERROR Listener: wrong password"); } Logger::Log(LOG_DEBUG, "user used the correct password, " - "creating client!"); - } else { - Logger::Log(LOG_DEBUG, "no password protection, creating client"); + "creating client!"); } - - //create a new client - m_sequencer->createClient(ts, *user); // copy the user info, since the buffer will be cleared soon + else + { + Logger::Log(LOG_DEBUG, "no password protection, creating client"); + //create a new client + } m_sequencer->createClient(ts, *user); // copy the user info, since the buffer will be cleared soon Logger::Log(LOG_DEBUG, "listener returned!"); } catch (std::runtime_error e) { diff --git a/source/server/listener.h b/source/server/listener.h index 47f1e466..0347f8de 100644 --- a/source/server/listener.h +++ b/source/server/listener.h @@ -1,22 +1,22 @@ /* - This file is part of "Rigs of Rods Server" (Relay mode) - - Copyright 2007 Pierre-Michel Ricordel - Copyright 2014+ Rigs of Rods Community - - "Rigs of Rods Server" is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation, either version 3 - of the License, or (at your option) any later version. - - "Rigs of Rods Server" is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -27,14 +27,15 @@ #include #include -class Listener { +class Listener +{ private: - pthread_t m_thread; - SWInetSocket m_listen_socket; - int m_listen_port; + pthread_t m_thread; + SWInetSocket m_listen_socket; + int m_listen_port; Threading::SimpleCond m_ready_cond; - Sequencer *m_sequencer; - std::atomic_bool m_thread_shutdown; + Sequencer *m_sequencer; + std::atomic_bool m_thread_shutdown; public: Listener(Sequencer *sequencer, int port); diff --git a/source/server/logger.cpp b/source/server/logger.cpp index cc2024aa..550a6e4d 100644 --- a/source/server/logger.cpp +++ b/source/server/logger.cpp @@ -1,23 +1,23 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2008 Christopher Ritchey (aka Aperion) -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2008 Christopher Ritchey (aka Aperion) + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "logger.h" @@ -37,29 +37,30 @@ along with Foobar. If not, see . #endif //_WIN32 -static FILE *s_file = nullptr; -static LogLevel s_log_level[2] = {LOG_VERBOSE, LOG_INFO}; -static const char *s_log_level_names[] = {"STACK", "DEBUG", "VERBO", "INFO", "WARN", "ERROR"}; +static FILE *s_file = nullptr; +static LogLevel s_log_level[2] = { LOG_VERBOSE, LOG_INFO }; +static const char *s_log_level_names[] = { "STACK", "DEBUG", "VERBO", "INFO", "WARN", "ERROR" }; static std::string s_log_filename = "server.log"; -static Mutex s_log_mutex; +static Mutex s_log_mutex; -// take care about mutexes: only manual lock in the Logger, otherwise you +// take care about mutexes: only manual lock in the Logger, otherwise you // could possibly start a recursion that ends in a deadlock // shamelessly taken from http://senzee.blogspot.com/2006/05/c-formatting-stdstring.html -std::string format_arg_list(const char *fmt, va_list args) { - if (!fmt) { +std::string format_arg_list(const char *fmt, va_list args) +{ + if (!fmt) return ""; - } - int result = -1, length = 256; + + int result = -1, length = 256; char *buffer = 0; - while (result == -1) { - if (buffer) { + while (result == -1) + { + if (buffer) delete[] buffer; - } buffer = new char[length + 1]; memset(buffer, 0, length + 1); - result = vsnprintf(buffer, length, fmt, args); + result = vsnprintf(buffer, length, fmt, args); length *= 2; } std::string s = Str::SanitizeUtf8(buffer); @@ -67,41 +68,45 @@ std::string format_arg_list(const char *fmt, va_list args) { return s; } -namespace Logger { - - void Log(const LogLevel &level, const char *format, ...) { +namespace Logger +{ + void Log(const LogLevel &level, const char *format, ...) + { va_list args; + va_start(args, format); Logger::Log(level, format_arg_list(format, args)); va_end(args); } - void Log(const LogLevel &level, const std::string &msg) { + void Log(const LogLevel &level, const std::string &msg) + { time_t current_time = time(nullptr); - char time_str[] = "DD-MM-YYYY hh:mm:ss"; // Placeholder + char time_str[] = "DD-MM-YYYY hh:mm:ss"; // Placeholder + strftime(time_str, 20, "%d-%m-%Y %H:%M:%S", localtime(¤t_time)); - const char *level_str = s_log_level_names[(int) level]; + const char *level_str = s_log_level_names[(int)level]; - if (level >= s_log_level[LOGTYPE_DISPLAY]) { + if (level >= s_log_level[LOGTYPE_DISPLAY]) printf("%s|t%02d|%5s|%s\n", time_str, ThreadID::getID(), level_str, msg.c_str()); - } // do not use the class for locking, otherwise you get recursion because of STACKLOG // UPDATE: 2016/05 only_a_ptr: STACKLOG was removed, TODO verify this pthread_mutex_lock(s_log_mutex.getRaw()); - if (s_file && level >= s_log_level[LOGTYPE_FILE]) { -/* FIXME If you need this feature, use copytruncate option for logrotate for now -#ifndef _WIN32 - - // check if we need to reopen the s_file (i.e. moved by logrotate) - struct stat mystat; - if (stat(s_log_filename.asUTF8_c_str(), &mystat)) - { - freopen(s_log_filename.asUTF8_c_str(), "a+", s_file); - } -#endif // _WIN32 -*/ + if (s_file && level >= s_log_level[LOGTYPE_FILE]) + { + /* FIXME If you need this feature, use copytruncate option for logrotate for now + * #ifndef _WIN32 + * + * // check if we need to reopen the s_file (i.e. moved by logrotate) + * struct stat mystat; + * if (stat(s_log_filename.asUTF8_c_str(), &mystat)) + * { + * freopen(s_log_filename.asUTF8_c_str(), "a+", s_file); + * } + * #endif // _WIN32 + */ fprintf(s_file, "%s|t%02d|%5s| %s\n", time_str, ThreadID::getID(), level_str, msg.c_str()); fflush(s_file); } @@ -109,20 +114,20 @@ namespace Logger { pthread_mutex_unlock(s_log_mutex.getRaw()); } - void SetOutputFile(const std::string &filename) { + void SetOutputFile(const std::string &filename) + { s_log_filename = filename; - if (s_file) { + if (s_file) fclose(s_file); - } s_file = fopen(s_log_filename.c_str(), - "a+"); // FIXME: This will fail on Windows, UTF-8 paths are not supported. + "a+"); // FIXME: This will fail on Windows, UTF-8 paths are not supported. // TODO Windows: research and convert the path to UTF-16 fprintf(s_file, "%s\n", "============================== RoR-Server started =============================="); } - void SetLogLevel(const LogType type, const LogLevel level) { - s_log_level[(int) type] = level; + void SetLogLevel(const LogType type, const LogLevel level) + { + s_log_level[(int)type] = level; } - } // namespace Logger diff --git a/source/server/logger.h b/source/server/logger.h index 06402206..fe8f61d5 100644 --- a/source/server/logger.h +++ b/source/server/logger.h @@ -1,29 +1,30 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2008 Christopher Ritchey (aka Aperion) -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2008 Christopher Ritchey (aka Aperion) + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once #include "UnicodeStrings.h" -enum LogLevel { +enum LogLevel +{ LOG_STACK = 0, LOG_DEBUG, LOG_VERBOSE, @@ -33,13 +34,14 @@ enum LogLevel { LOG_NONE }; -enum LogType { +enum LogType +{ LOGTYPE_FILE = 0, LOGTYPE_DISPLAY }; -namespace Logger { - +namespace Logger +{ void Log(const LogLevel &level, const char *format, ...); void Log(const LogLevel &level, const std::string &msg); @@ -47,5 +49,4 @@ namespace Logger { void SetOutputFile(const std::string &filename); void SetLogLevel(const LogType type, const LogLevel level); - } // namespace Logger diff --git a/source/server/master-server.cpp b/source/server/master-server.cpp index 03b285fa..3847e022 100644 --- a/source/server/master-server.cpp +++ b/source/server/master-server.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2016 Petr Ohlídal -Copyright 2016+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2016 Petr Ohlídal + * Copyright 2016+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "master-server.h" @@ -28,68 +28,80 @@ along with Foobar. If not, see . #include -namespace MasterServer { - +namespace MasterServer +{ Client::Client() : - m_trust_level(-1), - m_is_registered(false) {} + m_trust_level(-1), + m_is_registered(false) + { + } - bool Client::Register() { + bool Client::Register() + { Json::Value data(Json::objectValue); - data["ip"] = Config::getIPAddr(); - data["port"] = Config::getListenPort(); - data["name"] = Config::getServerName(); + + data["ip"] = Config::getIPAddr(); + data["port"] = Config::getListenPort(); + data["name"] = Config::getServerName(); data["terrain-name"] = Config::getTerrainName(); - data["max-clients"] = Config::getMaxClients(); - data["version"] = RORNET_VERSION; + data["max-clients"] = Config::getMaxClients(); + data["version"] = RORNET_VERSION; data["use-password"] = Config::isPublic(); m_server_path = "/" + Config::GetServerlistPath() + "/server-list"; Logger::Log(LOG_INFO, "Attempting to register on serverlist (%s)", m_server_path.c_str()); Http::Response response; - int result_code = this->HttpRequest(Http::METHOD_POST, data.toStyledString().c_str(), &response); - if (result_code < 0) { + int result_code = this->HttpRequest(Http::METHOD_POST, data.toStyledString().c_str(), &response); + if (result_code < 0) + { Logger::Log(LOG_ERROR, "Registration failed, result code: %d", result_code); return false; - } else if (result_code != 200) { + } + else if (result_code != 200) + { Logger::Log(LOG_INFO, "Registration failed, response code: HTTP %d, body: %s", result_code, response.GetBody().c_str()); return false; } - Json::Value root; + Json::Value root; Json::Reader reader; - if (!reader.parse(response.GetBody().c_str(), root)) { + if (!reader.parse(response.GetBody().c_str(), root)) + { Logger::Log(LOG_ERROR, "Registration failed, invalid server response (JSON parsing failed)"); Logger::Log(LOG_DEBUG, "Raw response: %s", response.GetBody().c_str()); return false; } Json::Value trust_level = root["verified-level"]; - Json::Value challenge = root["challenge"]; - if (!root.isObject() || !trust_level.isNumeric() || !challenge.isString()) { + Json::Value challenge = root["challenge"]; + if (!root.isObject() || !trust_level.isNumeric() || !challenge.isString()) + { Logger::Log(LOG_ERROR, "Registration failed, incorrect response from server"); Logger::Log(LOG_DEBUG, "Raw response: %s", response.GetBody().c_str()); return false; } - m_token = challenge.asString(); - m_trust_level = trust_level.asInt(); + m_token = challenge.asString(); + m_trust_level = trust_level.asInt(); m_is_registered = true; return true; } - bool Client::SendHeatbeat(Json::Value user_list) { + bool Client::SendHeatbeat(Json::Value user_list) + { Json::Value data(Json::objectValue); + data["challenge"] = m_token; - data["users"] = user_list; + data["users"] = user_list; std::string json_str = data.toStyledString(); Logger::Log(LOG_DEBUG, "Heartbeat JSON:\n%s", json_str.c_str()); Http::Response response; - int result_code = this->HttpRequest(Http::METHOD_PUT, json_str.c_str(), &response); - if (result_code != 200) { + int result_code = this->HttpRequest(Http::METHOD_PUT, json_str.c_str(), &response); + if (result_code != 200) + { const char *type = (result_code < 0) ? "result code" : "HTTP code"; Logger::Log(LOG_ERROR, "Heatbeat failed, %s: %d", type, result_code); return false; @@ -97,7 +109,8 @@ namespace MasterServer { return true; } - bool Client::UnRegister() { + bool Client::UnRegister() + { assert(m_is_registered == true); Json::Value data(Json::objectValue); @@ -106,8 +119,9 @@ namespace MasterServer { Logger::Log(LOG_DEBUG, "UnRegister JSON:\n%s", json_str.c_str()); Http::Response response; - int result_code = this->HttpRequest(Http::METHOD_DELETE, json_str.c_str(), &response); - if (result_code < 0) { + int result_code = this->HttpRequest(Http::METHOD_DELETE, json_str.c_str(), &response); + if (result_code < 0) + { const char *type = (result_code < 0) ? "result code" : "HTTP code"; Logger::Log(LOG_ERROR, "Failed to un-register server, %s: %d", type, result_code); return false; @@ -116,26 +130,29 @@ namespace MasterServer { return true; } -// Helper - int Client::HttpRequest(const char *method, const char *payload, Http::Response *out_response) { + // Helper + int Client::HttpRequest(const char *method, const char *payload, Http::Response *out_response) + { return Http::Request(method, Config::GetServerlistHostC(), m_server_path.c_str(), "application/json", payload, out_response); } - bool RetrievePublicIp() { + bool RetrievePublicIp() + { char url[300] = ""; + sprintf(url, "/%s/get-public-ip", Config::GetServerlistPath().c_str()); Http::Response response; - int result_code = Http::Request(Http::METHOD_GET, - Config::GetServerlistHostC(), url, "application/json", "", &response); - if (result_code < 0) { + int result_code = Http::Request(Http::METHOD_GET, + Config::GetServerlistHostC(), url, "application/json", "", &response); + if (result_code < 0) + { Logger::Log(LOG_ERROR, "Failed to retrieve public IP address"); return false; } Config::setIPAddr(response.GetBody()); return true; } - } // namespace MasterServer diff --git a/source/server/master-server.h b/source/server/master-server.h index 6c1c3849..66376bd7 100644 --- a/source/server/master-server.h +++ b/source/server/master-server.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2016 Petr Ohlídal -Copyright 2016+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2016 Petr Ohlídal + * Copyright 2016+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -25,10 +25,11 @@ along with Foobar. If not, see . #include "json/json.h" -namespace MasterServer { - - class Client { - public: +namespace MasterServer +{ + class Client + { +public: Client(); bool Register(); @@ -37,20 +38,25 @@ namespace MasterServer { bool UnRegister(); - bool IsRegistered() const { return m_is_registered; } + bool IsRegistered() const + { + return m_is_registered; + } - int GetTrustLevel() const { return m_trust_level; } + int GetTrustLevel() const + { + return m_trust_level; + } - private: - int HttpRequest(const char *method, const char *payload, Http::Response *out_response); ///< Helper +private: + int HttpRequest(const char *method, const char *payload, Http::Response *out_response); ///< Helper std::string m_token; - int m_trust_level; - bool m_is_registered; + int m_trust_level; + bool m_is_registered; std::string m_server_path; }; bool RetrievePublicIp(); - } // namespace MasterServer diff --git a/source/server/messaging.cpp b/source/server/messaging.cpp index 84c4707e..00cac09d 100644 --- a/source/server/messaging.cpp +++ b/source/server/messaging.cpp @@ -1,23 +1,23 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with "Rigs of Rods Server". -If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". + * If not, see . + */ #include "messaging.h" @@ -36,72 +36,80 @@ If not, see . #include -static stream_traffic_t s_traffic = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static std::mutex s_traffic_mutex; - -namespace Messaging { +static stream_traffic_t s_traffic = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static std::mutex s_traffic_mutex; - void UpdateMinuteStats() { +namespace Messaging +{ + void UpdateMinuteStats() + { std::unique_lock lock(s_traffic_mutex); // normal bandwidth - s_traffic.bandwidthIncomingRate = (s_traffic.bandwidthIncoming - s_traffic.bandwidthIncomingLastMinute) / 60; + s_traffic.bandwidthIncomingRate = (s_traffic.bandwidthIncoming - s_traffic.bandwidthIncomingLastMinute) / 60; s_traffic.bandwidthIncomingLastMinute = s_traffic.bandwidthIncoming; - s_traffic.bandwidthOutgoingRate = (s_traffic.bandwidthOutgoing - s_traffic.bandwidthOutgoingLastMinute) / 60; + s_traffic.bandwidthOutgoingRate = (s_traffic.bandwidthOutgoing - s_traffic.bandwidthOutgoingLastMinute) / 60; s_traffic.bandwidthOutgoingLastMinute = s_traffic.bandwidthOutgoing; // dropped bandwidth s_traffic.bandwidthDropIncomingRate = - (s_traffic.bandwidthDropIncoming - s_traffic.bandwidthDropIncomingLastMinute) / 60; + (s_traffic.bandwidthDropIncoming - s_traffic.bandwidthDropIncomingLastMinute) / 60; s_traffic.bandwidthDropIncomingLastMinute = s_traffic.bandwidthDropIncoming; - s_traffic.bandwidthDropOutgoingRate = - (s_traffic.bandwidthDropOutgoing - s_traffic.bandwidthDropOutgoingLastMinute) / 60; + s_traffic.bandwidthDropOutgoingRate = + (s_traffic.bandwidthDropOutgoing - s_traffic.bandwidthDropOutgoingLastMinute) / 60; s_traffic.bandwidthDropOutgoingLastMinute = s_traffic.bandwidthDropOutgoing; } - void StatsAddIncoming(int bytes) { + void StatsAddIncoming(int bytes) + { std::unique_lock lock(s_traffic_mutex); s_traffic.bandwidthIncoming += static_cast(bytes); } - void StatsAddOutgoing(int bytes) { + void StatsAddOutgoing(int bytes) + { std::unique_lock lock(s_traffic_mutex); s_traffic.bandwidthOutgoing += static_cast(bytes); } - void StatsAddIncomingDrop(int bytes) { + void StatsAddIncomingDrop(int bytes) + { std::unique_lock lock(s_traffic_mutex); s_traffic.bandwidthDropIncoming += static_cast(bytes); } - void StatsAddOutgoingDrop(int bytes) { + void StatsAddOutgoingDrop(int bytes) + { std::unique_lock lock(s_traffic_mutex); s_traffic.bandwidthDropOutgoing += static_cast(bytes); } - stream_traffic_t GetTrafficStats() { + stream_traffic_t GetTrafficStats() + { std::unique_lock lock(s_traffic_mutex); return s_traffic; } -/** - * @param socket Socket to communicate over - * @param type Command ID - * @param source Source ID - * @param len Data length - * @param content Payload - * @return 0 on success - */ + /** + * @param socket Socket to communicate over + * @param type Command ID + * @param source Source ID + * @param len Data length + * @param content Payload + * @return 0 on success + */ int SendMessage(SWInetSocket *socket, int type, int source, unsigned int streamid, unsigned int len, - const char *content) { + const char *content) + { assert(socket != nullptr); SWBaseSocket::SWBaseError error; - RoRnet::Header head; + RoRnet::Header head; - const int msgsize = sizeof(RoRnet::Header) + len; + const int msgsize = sizeof(RoRnet::Header) + len; - if (msgsize >= RORNET_MAX_MESSAGE_LENGTH) { + if (msgsize >= RORNET_MAX_MESSAGE_LENGTH) + { Logger::Log(LOG_ERROR, "UID: %d - attempt to send too long message", source); return -4; } @@ -112,19 +120,21 @@ namespace Messaging { int rlen = 0; memset(&head, 0, sizeof(RoRnet::Header)); - head.command = type; - head.source = source; - head.size = len; + head.command = type; + head.source = source; + head.size = len; head.streamid = streamid; // construct buffer memset(buffer, 0, RORNET_MAX_MESSAGE_LENGTH); - memcpy(buffer, (char *) &head, sizeof(RoRnet::Header)); + memcpy(buffer, (char*)&head, sizeof(RoRnet::Header)); memcpy(buffer + sizeof(RoRnet::Header), content, len); - while (rlen < msgsize) { + while (rlen < msgsize) + { int sendnum = socket->send(buffer + rlen, msgsize - rlen, &error); - if (sendnum < 0 || error != SWBaseSocket::ok) { + if (sendnum < 0 || error != SWBaseSocket::ok) + { Logger::Log(LOG_ERROR, "send error -1: %s", error.get_error().c_str()); return -1; } @@ -134,32 +144,35 @@ namespace Messaging { return 0; } -/** - * @param out_type Message type, see RoRnet::RoRnet::MSG2_* macros in rornet.h - * @param out_source Magic. Value 5000 used by serverlist to check this server. - * @return 0 on success, negative number on error. - */ + /** + * @param out_type Message type, see RoRnet::RoRnet::MSG2_* macros in rornet.h + * @param out_source Magic. Value 5000 used by serverlist to check this server. + * @return 0 on success, negative number on error. + */ int ReceiveMessage( - SWInetSocket *socket, - int *out_type, - int *out_source, - unsigned int *out_stream_id, - unsigned int *out_payload_len, - char *out_payload, - unsigned int payload_buf_len) { + SWInetSocket *socket, + int *out_type, + int *out_source, + unsigned int *out_stream_id, + unsigned int *out_payload_len, + char *out_payload, + unsigned int payload_buf_len) + { assert(socket != nullptr); assert(out_type != nullptr); assert(out_source != nullptr); assert(out_stream_id != nullptr); assert(out_payload != nullptr); - char buffer[RORNET_MAX_MESSAGE_LENGTH] = {}; + char buffer[RORNET_MAX_MESSAGE_LENGTH] = {}; - int hlen = 0; + int hlen = 0; SWBaseSocket::SWBaseError error; - while (hlen < (int) sizeof(RoRnet::Header)) { + while (hlen < (int)sizeof(RoRnet::Header)) + { int recvnum = socket->recv(buffer + hlen, sizeof(RoRnet::Header) - hlen, &error); - if (recvnum < 0 || error != SWBaseSocket::ok) { + if (recvnum < 0 || error != SWBaseSocket::ok) + { Logger::Log(LOG_ERROR, "receive error -2: %s", error.get_error().c_str()); // this also happens when the connection is canceled return -2; @@ -169,45 +182,51 @@ namespace Messaging { RoRnet::Header head; memcpy(&head, buffer, sizeof(RoRnet::Header)); - *out_type = head.command; - *out_source = head.source; + *out_type = head.command; + *out_source = head.source; *out_payload_len = head.size; - *out_stream_id = head.streamid; + *out_stream_id = head.streamid; - if ((int) head.size >= RORNET_MAX_MESSAGE_LENGTH) { + if ((int)head.size >= RORNET_MAX_MESSAGE_LENGTH) + { Logger::Log(LOG_ERROR, "ReceiveMessage(): payload too long: %d b (max. is %d b)", head.size, RORNET_MAX_MESSAGE_LENGTH); return -3; } - if (head.size > 0) { + if (head.size > 0) //read the rest - while (hlen < (int) sizeof(RoRnet::Header) + (int) head.size) { + while (hlen < (int)sizeof(RoRnet::Header) + (int)head.size) + { int recvnum = socket->recv(buffer + hlen, (head.size + sizeof(RoRnet::Header)) - hlen, &error); - if (recvnum < 0 || error != SWBaseSocket::ok) { + if (recvnum < 0 || error != SWBaseSocket::ok) + { Logger::Log(LOG_ERROR, "receive error -1: %s", error.get_error().c_str()); return -1; } hlen += recvnum; } - } - StatsAddIncoming((int) sizeof(RoRnet::Header) + (int) head.size); + StatsAddIncoming((int)sizeof(RoRnet::Header) + (int)head.size); memcpy(out_payload, buffer + sizeof(RoRnet::Header), payload_buf_len); return 0; } - int getTime() { return (int) time(NULL); } + int getTime() + { + return (int)time(NULL); + } - int broadcastLAN() { + int broadcastLAN() + { #ifdef _WIN32 // since socketw only abstracts TCP, we are on our own with UDP here :-/ // the following code was only tested under windows - int sockfd = -1; - int on = 1; + int sockfd = -1; + int on = 1; struct sockaddr_in sendaddr; memset(&sendaddr, 0, sizeof(sendaddr)); struct sockaddr_in recvaddr; @@ -225,17 +244,17 @@ namespace Messaging { Logger::Log(LOG_ERROR, "error creating socket for LAN broadcast: %s", strerror(errno)); return 1; } - if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const char *)&on, sizeof(on)) < 0) + if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof(on)) < 0) { Logger::Log(LOG_ERROR, "error setting socket options for LAN broadcast: %s", strerror(errno)); return 2; } sendaddr.sin_family = AF_INET; - sendaddr.sin_port = htons(RORNET_LAN_BROADCAST_PORT+1); + sendaddr.sin_port = htons(RORNET_LAN_BROADCAST_PORT + 1); sendaddr.sin_addr.s_addr = htonl(INADDR_ANY); - if (bind(sockfd, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) == SOCKET_ERROR) + if (bind(sockfd, (struct sockaddr*)&sendaddr, sizeof(sendaddr)) == SOCKET_ERROR) { Logger::Log(LOG_ERROR, "error binding socket for LAN broadcast: %s", strerror(errno)); return 3; @@ -253,16 +272,16 @@ namespace Messaging { // RoRServer|Protocol V |IP :PORT |terrain name |password protected? // RoRServer|RoRnet_2.35|192.168.0.235:12001|myterrain.terrn|0 sprintf(tmp, "RoRServer|%s|%s:%d|%s|%d", - RORNET_VERSION, - Config::getIPAddr().c_str(), - Config::getListenPort(), - Config::getTerrainName().c_str(), - Config::getPublicPassword() == "" ? 0 : 1 - ); + RORNET_VERSION, + Config::getIPAddr().c_str(), + Config::getListenPort(), + Config::getTerrainName().c_str(), + Config::getPublicPassword() == "" ? 0 : 1 + ); // send the message int numbytes = 0; - while((numbytes = sendto(sockfd, tmp, strnlen(tmp, 1024), 0, (struct sockaddr *)&recvaddr, sizeof recvaddr)) < -1) + while ((numbytes = sendto(sockfd, tmp, strnlen(tmp, 1024), 0, (struct sockaddr*)&recvaddr, sizeof recvaddr)) < -1) { Logger::Log(LOG_ERROR, "error sending data over socket for LAN broadcast: %s", strerror(errno)); return 4; @@ -272,8 +291,7 @@ namespace Messaging { closesocket(sockfd); Logger::Log(LOG_DEBUG, "LAN broadcast successful"); -#endif // _WIN32 +#endif // _WIN32 return 0; } - } // namespace Messaging diff --git a/source/server/messaging.h b/source/server/messaging.h index aebc52d1..82ef5d08 100644 --- a/source/server/messaging.h +++ b/source/server/messaging.h @@ -1,47 +1,47 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with "Rigs of Rods Server". -If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". + * If not, see . + */ #pragma once #include "sequencer.h" #include "prerequisites.h" -namespace Messaging { - +namespace Messaging +{ int SendMessage( - SWInetSocket *socket, - int msg_type, - int msg_client_id, - unsigned int msg_stream_id, - unsigned int payload_len, - const char *payload); + SWInetSocket *socket, + int msg_type, + int msg_client_id, + unsigned int msg_stream_id, + unsigned int payload_len, + const char *payload); int ReceiveMessage( - SWInetSocket *socket, - int *out_msg_type, - int *out_client_id, - unsigned int *out_stream_id, - unsigned int *out_payload_len, - char *out_payload, - unsigned int payload_buf_len); + SWInetSocket *socket, + int *out_msg_type, + int *out_client_id, + unsigned int *out_stream_id, + unsigned int *out_payload_len, + char *out_payload, + unsigned int payload_buf_len); int broadcastLAN(); @@ -54,5 +54,4 @@ namespace Messaging { void UpdateMinuteStats(); int getTime(); - } // namespace Messaging diff --git a/source/server/mongoose.h b/source/server/mongoose.h index 4d4c8c0a..7eb004e8 100644 --- a/source/server/mongoose.h +++ b/source/server/mongoose.h @@ -36,23 +36,25 @@ struct mg_connection; /* Handle for the individual connection */ * This structure contains full information about the HTTP request. * It is passed to the user-specified callback function as a parameter. */ -struct mg_request_info { - char *request_method; /* "GET", "POST", etc */ - char *uri; /* Normalized URI */ - char *query_string; /* \0 - terminated */ - char *post_data; /* POST data buffer */ - char *remote_user; /* Authenticated user */ +struct mg_request_info +{ + char *request_method; /* "GET", "POST", etc */ + char *uri; /* Normalized URI */ + char *query_string; /* \0 - terminated */ + char *post_data; /* POST data buffer */ + char *remote_user; /* Authenticated user */ long remote_ip; /* Client's IP address */ - int remote_port; /* Client's port */ - int post_data_len; /* POST buffer length */ - int http_version_major; - int http_version_minor; - int status_code; /* HTTP status code */ - int num_headers; /* Number of headers */ - struct mg_header { - char *name; /* HTTP header name */ + int remote_port; /* Client's port */ + int post_data_len; /* POST buffer length */ + int http_version_major; + int http_version_minor; + int status_code; /* HTTP status code */ + int num_headers; /* Number of headers */ + struct mg_header + { + char *name; /* HTTP header name */ char *value; /* HTTP header value */ - } http_headers[64]; /* Maximum 64 headers */ + } http_headers[64]; /* Maximum 64 headers */ }; @@ -98,7 +100,7 @@ const char *mg_get_option(const struct mg_context *, const char *option_name); * Return value: * -1 if option is unknown * 0 if mg_set_option() failed - * 1 if mg_set_option() succeeded + * 1 if mg_set_option() succeeded */ int mg_set_option(struct mg_context *, const char *opt_name, const char *value); @@ -113,7 +115,7 @@ int mg_set_option(struct mg_context *, const char *opt_name, const char *value); * If password is not NULL, entry is added (or modified if already exists). * If password is NULL, entry is deleted. Return: * 1 on success - * 0 on error + * 0 on error */ int mg_modify_passwords_file(struct mg_context *ctx, const char *file_name, const char *user_name, const char *password); @@ -220,7 +222,7 @@ void mg_authorize(struct mg_connection *); * NULL if the variable is not found * non-NULL if found. NOTE: this returned value is dynamically allocated * and is subject to mg_free() when no longer needed. It is - * an application's responsibility to mg_free() the variable. + * an application's responsibility to mg_free() the variable. */ char *mg_get_var(const struct mg_connection *, const char *var_name); diff --git a/source/server/mutexutils.cpp b/source/server/mutexutils.cpp index bd159806..83538925 100644 --- a/source/server/mutexutils.cpp +++ b/source/server/mutexutils.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "mutexutils.h" @@ -25,17 +25,33 @@ along with Foobar. If not, see . #include #include -Condition::Condition() { pthread_cond_init(&cond, NULL); } +Condition::Condition() +{ + pthread_cond_init(&cond, NULL); +} -Condition::~Condition() { pthread_cond_destroy(&cond); } +Condition::~Condition() +{ + pthread_cond_destroy(&cond); +} -void Condition::signal() { pthread_cond_signal(&cond); } +void Condition::signal() +{ + pthread_cond_signal(&cond); +} -Mutex::Mutex() : lock_owner(0) { pthread_mutex_init(&m, NULL); } +Mutex::Mutex() : lock_owner(0) +{ + pthread_mutex_init(&m, NULL); +} -Mutex::~Mutex() { pthread_mutex_destroy(&m); } +Mutex::~Mutex() +{ + pthread_mutex_destroy(&m); +} -void Mutex::lock() { +void Mutex::lock() +{ // check for deadlock, if this occurs raise an abort signal to stop the // debugger @@ -45,53 +61,75 @@ void Mutex::lock() { lock_owner = ThreadID::getID(); } -void Mutex::unlock() { +void Mutex::unlock() +{ pthread_mutex_unlock(&m); lock_owner = 0; } -void Mutex::wait(Condition &c) { pthread_cond_wait(&(c.cond), &m); } +void Mutex::wait(Condition &c) +{ + pthread_cond_wait(&(c.cond), &m); +} -MutexLocker::MutexLocker(Mutex &pm) : m(pm) { m.lock(); } +MutexLocker::MutexLocker(Mutex &pm) : m(pm) +{ + m.lock(); +} -MutexLocker::~MutexLocker() { m.unlock(); } +MutexLocker::~MutexLocker() +{ + m.unlock(); +} -pthread_key_t ThreadID::key; +pthread_key_t ThreadID::key; pthread_once_t ThreadID::key_once = PTHREAD_ONCE_INIT; -unsigned int ThreadID::tuid = 1; +unsigned int ThreadID::tuid = 1; -unsigned int ThreadID::getID() { +unsigned int ThreadID::getID() +{ ThreadID *ptr = NULL; + pthread_once(&key_once, ThreadID::make_key); - ptr = (ThreadID *) pthread_getspecific(key); + ptr = (ThreadID*)pthread_getspecific(key); - if (!ptr) { + if (!ptr) + { ptr = new ThreadID(); - pthread_setspecific(key, (void *) ptr); + pthread_setspecific(key, (void*)ptr); } return ptr->thread_id; } -ThreadID::ThreadID() : thread_id(tuid) { tuid++; } - -void ThreadID::make_key() { pthread_key_create(&key, NULL); } +ThreadID::ThreadID() : thread_id(tuid) +{ + tuid++; +} -namespace Threading { +void ThreadID::make_key() +{ + pthread_key_create(&key, NULL); +} - bool SimpleCond::Initialize() { +namespace Threading +{ + bool SimpleCond::Initialize() + { assert(m_value == INACTIVE); int result = pthread_mutex_init(&m_mutex, nullptr); - if (result != 0) { + if (result != 0) + { Logger::Log(LOG_ERROR, "Internal error: Failed to initialize mutex, error code: %d [in SimpleCond::Initialize()]", result); return false; } int cond_result = pthread_cond_init(&m_cond, nullptr); - if (cond_result != 0) { + if (cond_result != 0) + { Logger::Log(LOG_ERROR, "Internal error: Failed to initialize condition variable, error code: %d [in SimpleCond::Initialize()]", cond_result); @@ -101,17 +139,20 @@ namespace Threading { return true; } - bool SimpleCond::Destroy() { + bool SimpleCond::Destroy() + { assert(m_value != INACTIVE); int result = pthread_mutex_destroy(&m_mutex); - if (result != 0) { + if (result != 0) + { Logger::Log(LOG_WARN, "Internal: Failed to destroy mutex, error code: %d [in SimpleCond::Destroy()]", result); return false; } int cond_result = pthread_cond_destroy(&m_cond); - if (cond_result != 0) { + if (cond_result != 0) + { Logger::Log(LOG_WARN, "Internal: Failed to destroy condition variable, error code: %d [in SimpleCond::Destroy()]", cond_result); @@ -121,16 +162,19 @@ namespace Threading { return true; } - bool SimpleCond::Wait(int *out_value) { + bool SimpleCond::Wait(int *out_value) + { assert(out_value != nullptr); - if (!this->Lock("SimpleCond::Wait()")) { + if (!this->Lock("SimpleCond::Wait()")) return false; - } - while (m_value == 0) { + + while (m_value == 0) + { int wait_result = pthread_cond_wait(&m_cond, &m_mutex); - if (wait_result != 0) { + if (wait_result != 0) + { Logger::Log(LOG_ERROR, "Internal error: Failed to wait on condition variable, error code: %d [in SimpleCond::Wait()]", wait_result); @@ -140,22 +184,24 @@ namespace Threading { } *out_value = m_value; - if (!this->Unlock("SimpleCond::Wait()")) { + if (!this->Unlock("SimpleCond::Wait()")) return false; - } + return true; } - bool SimpleCond::Signal(int value) { + bool SimpleCond::Signal(int value) + { assert(m_value != INACTIVE); - if (!this->Lock("SimpleCond::Signal()")) { + if (!this->Lock("SimpleCond::Signal()")) return false; - } + m_value = value; int signal_result = pthread_cond_signal(&m_cond); - if (signal_result != 0) { + if (signal_result != 0) + { Logger::Log(LOG_ERROR, "Internal error: Failed to signal condition variable, error code: %d [in SimpleCond::Signal()]", signal_result); @@ -163,15 +209,18 @@ namespace Threading { return false; } - if (!this->Unlock("SimpleCond::Signal()")) { + if (!this->Unlock("SimpleCond::Signal()")) return false; - } + return true; } - bool SimpleCond::Lock(const char *log_location) { + bool SimpleCond::Lock(const char *log_location) + { int lock_result = pthread_mutex_lock(&m_mutex); - if (lock_result != 0) { + + if (lock_result != 0) + { Logger::Log(LOG_ERROR, "Internal: Failed to acquire lock, error code: %d [in %s]", lock_result, log_location); return false; @@ -179,15 +228,17 @@ namespace Threading { return true; } - bool SimpleCond::Unlock(const char *log_location) { + bool SimpleCond::Unlock(const char *log_location) + { int unlock_result = pthread_mutex_unlock(&m_mutex); - if (unlock_result != 0) { + + if (unlock_result != 0) + { Logger::Log(LOG_ERROR, "Internal: Failed to remove lock, error code: %d [in %s]", unlock_result, log_location); return false; } return true; } - } diff --git a/source/server/mutexutils.h b/source/server/mutexutils.h index 3a55d5ae..01fae780 100644 --- a/source/server/mutexutils.h +++ b/source/server/mutexutils.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -24,13 +24,16 @@ along with Foobar. If not, see . #define USE_THREADID -namespace Threading { - - class SimpleCond { - public: +namespace Threading +{ + class SimpleCond + { +public: static const int INACTIVE = 0xFEFEFEFE; - SimpleCond() : m_value(INACTIVE) {} + SimpleCond() : m_value(INACTIVE) + { + } bool Initialize(); @@ -40,19 +43,19 @@ namespace Threading { bool Signal(int value); - private: +private: bool Lock(const char *log_location); bool Unlock(const char *log_location); - pthread_cond_t m_cond; + pthread_cond_t m_cond; pthread_mutex_t m_mutex; - int m_value; + int m_value; }; - } -class Condition { +class Condition +{ friend class Mutex; public: @@ -67,7 +70,8 @@ class Condition { }; -class Mutex { +class Mutex +{ public: Mutex(); @@ -79,15 +83,19 @@ class Mutex { void wait(Condition &c); - pthread_mutex_t *getRaw() { return &m; }; + pthread_mutex_t *getRaw() + { + return &m; + }; private: pthread_mutex_t m; - unsigned int lock_owner; + unsigned int lock_owner; }; -class MutexLocker { +class MutexLocker +{ public: MutexLocker(Mutex &pm); @@ -97,8 +105,8 @@ class MutexLocker { Mutex &m; }; -class ThreadID { - +class ThreadID +{ public: static unsigned int getID(); @@ -107,8 +115,8 @@ class ThreadID { static void make_key(); - unsigned int thread_id; - static pthread_key_t key; + unsigned int thread_id; + static pthread_key_t key; static pthread_once_t key_once; - static unsigned int tuid; + static unsigned int tuid; }; diff --git a/source/server/prerequisites.h b/source/server/prerequisites.h index e1c20216..a9054a2a 100644 --- a/source/server/prerequisites.h +++ b/source/server/prerequisites.h @@ -16,6 +16,7 @@ class UserAuth; class ScriptEngine; -namespace Http { +namespace Http +{ class Response; } \ No newline at end of file diff --git a/source/server/receiver.cpp b/source/server/receiver.cpp index a03ac812..607978d0 100644 --- a/source/server/receiver.cpp +++ b/source/server/receiver.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "receiver.h" @@ -26,47 +26,54 @@ along with Foobar. If not, see . #include "ScriptEngine.h" #include "logger.h" -void *LaunchReceiverThread(void *data) { +void *LaunchReceiverThread(void *data) +{ Receiver *receiver = static_cast(data); + receiver->Thread(); return nullptr; } Receiver::Receiver(Sequencer *sequencer) : - m_id(0), - m_socket(nullptr), - m_is_running(false), - m_sequencer(sequencer) { + m_id(0), + m_socket(nullptr), + m_is_running(false), + m_sequencer(sequencer) +{ } -Receiver::~Receiver(void) { +Receiver::~Receiver(void) +{ Stop(); } -void Receiver::Start(int pos, SWInetSocket *socky) { - m_id = pos; - m_socket = socky; +void Receiver::Start(int pos, SWInetSocket *socky) +{ + m_id = pos; + m_socket = socky; m_is_running = true; pthread_create(&m_thread, nullptr, LaunchReceiverThread, this); } -void Receiver::Stop() { - if (!m_is_running) { +void Receiver::Stop() +{ + if (!m_is_running) return; - } + m_is_running = false; pthread_join(m_thread, nullptr); } -void Receiver::Thread() { +void Receiver::Thread() +{ Logger::Log(LOG_DEBUG, "receiver thread %d owned by uid %d", ThreadID::getID(), m_id); //get the vehicle description - int type; - int source; - unsigned int streamid; - unsigned int len; + int type; + int source; + unsigned int streamid; + unsigned int len; SWBaseSocket::SWBaseError error; //okay, we are ready, we can receive data frames m_sequencer->enableFlow(m_id); @@ -79,22 +86,23 @@ void Receiver::Thread() { // this prevents the socket from hangingwhen sending data // which is the cause of threads getting blocked m_socket->set_timeout(60, 0); - while (m_is_running) { + while (m_is_running) + { if (Messaging::ReceiveMessage(m_socket, &type, &source, &streamid, &len, m_dbuffer, - RORNET_MAX_MESSAGE_LENGTH)) { + RORNET_MAX_MESSAGE_LENGTH)) + { m_sequencer->disconnect(m_id, "Game connection closed"); break; } - if (!m_is_running) { + if (!m_is_running) break; - } - if (type != RoRnet::MSG2_STREAM_DATA) { + if (type != RoRnet::MSG2_STREAM_DATA) Logger::Log(LOG_VERBOSE, "got message: type: %d, source: %d:%d, len: %d", type, source, streamid, len); - } - if (type < 1000 || type > 1050) { + if (type < 1000 || type > 1050) + { m_sequencer->disconnect(m_id, "Protocol error 3"); break; } diff --git a/source/server/receiver.h b/source/server/receiver.h index 5dfef400..0a60e050 100644 --- a/source/server/receiver.h +++ b/source/server/receiver.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -30,7 +30,8 @@ class Sequencer; void *LaunchReceiverThread(void *); -class Receiver { +class Receiver +{ friend void *LaunchReceiverThread(void *); public: @@ -45,11 +46,11 @@ class Receiver { private: void Thread(); - pthread_t m_thread; - int m_id; + pthread_t m_thread; + int m_id; SWInetSocket *m_socket; - char m_dbuffer[RORNET_MAX_MESSAGE_LENGTH]; - bool m_is_running; - Sequencer *m_sequencer; + char m_dbuffer[RORNET_MAX_MESSAGE_LENGTH]; + bool m_is_running; + Sequencer *m_sequencer; }; diff --git a/source/server/resource.h b/source/server/resource.h index 638f71a9..294051be 100644 --- a/source/server/resource.h +++ b/source/server/resource.h @@ -2,15 +2,15 @@ // Microsoft Developer Studio generated include file. // Used by icon.rc // -#define IDI_ICON1 101 +#define IDI_ICON1 101 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/source/server/rorserver.cpp b/source/server/rorserver.cpp index 3b815d2a..db7b2cb2 100644 --- a/source/server/rorserver.cpp +++ b/source/server/rorserver.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ // RoRserver.cpp : Defines the entry point for the console application. @@ -57,43 +57,52 @@ along with Foobar. If not, see . #endif // _WIN32 -static Sequencer s_sequencer; +static Sequencer s_sequencer; static MasterServer::Client s_master_server; -static bool s_exit_requested = false; +static bool s_exit_requested = false; #ifndef _WIN32 -void handler(int signalnum) { - if (s_exit_requested) { +void handler(int signalnum) +{ + if (s_exit_requested) return; - } + s_exit_requested = true; // reject handler signal(signalnum, handler); bool terminate = false; - if (signalnum == SIGINT) { + if (signalnum == SIGINT) + { Logger::Log(LOG_ERROR, "got interrupt signal, terminating ..."); terminate = true; - } else if (signalnum == SIGTERM) { + } + else if (signalnum == SIGTERM) + { Logger::Log(LOG_ERROR, "got terminate signal, terminating ..."); terminate = true; - } else if (signalnum == SIGHUP) { + } + else if (signalnum == SIGHUP) + { Logger::Log(LOG_ERROR, "got HUP signal, terminating ..."); terminate = true; - } else { - Logger::Log(LOG_ERROR, "got unkown signal: %d", signal); } - - if (terminate) { - if (Config::getServerMode() == SERVER_LAN) { + else + { + Logger::Log(LOG_ERROR, "got unkown signal: %d", signal); + } if (terminate) + { + if (Config::getServerMode() == SERVER_LAN) + { Logger::Log(LOG_ERROR, "closing server ... "); s_sequencer.Close(); - } else { + } + else + { Logger::Log(LOG_INFO, "closing server ... unregistering ... "); - if (s_master_server.IsRegistered()) { + if (s_master_server.IsRegistered()) s_master_server.UnRegister(); - } s_sequencer.Close(); } exit(0); @@ -111,18 +120,22 @@ BOOL WINAPI WindowsConsoleHandlerRoutine(DWORD ctrl_type) case CTRL_C_EVENT: Logger::Log(LOG_INFO, "Received `Ctrl+C` event."); break; + case CTRL_BREAK_EVENT: Logger::Log(LOG_INFO, "Received `Ctrl+Break` event."); break; + case CTRL_CLOSE_EVENT: Logger::Log(LOG_INFO, "Received `Close` event."); break; + case CTRL_SHUTDOWN_EVENT: Logger::Log(LOG_INFO, "Received `System shutdown` event."); break; + default: Logger::Log(LOG_WARN, "Received unknown console event: %lu.", static_cast(ctrl_type)); - return TRUE; // Means 'event handled' + return TRUE; // Means 'event handled' } if (s_master_server.IsRegistered()) @@ -132,7 +145,7 @@ BOOL WINAPI WindowsConsoleHandlerRoutine(DWORD ctrl_type) } s_sequencer.Close(); // TODO: This somehow closes (crashes?) the process on Windows, debugger doesn't intercept anything... Logger::Log(LOG_INFO, "Clean exit (Windows)"); - ExitProcess(0); // Recommended by MSDN, see above link. + ExitProcess(0); // Recommended by MSDN, see above link. } #endif @@ -142,27 +155,33 @@ BOOL WINAPI WindowsConsoleHandlerRoutine(DWORD ctrl_type) // from http://www.enderunix.org/docs/eng/daemon.php // also http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize -#define LOCK_FILE "rorserver.lock" +#define LOCK_FILE "rorserver.lock" -void daemonize() { - if (getppid() == 1) { +void daemonize() +{ + if (getppid() == 1) /* already a daemon */ return; - } + /* Drop user if there is one, and we were run as root */ const char *username = "rorserver"; // TODO: add flexibility to change the username via cmdline - if (getuid() == 0 || geteuid() == 0) { + if (getuid() == 0 || geteuid() == 0) + { Logger::Log(LOG_VERBOSE, "changing user to %s", username); struct passwd *pw = getpwnam(username); - if (pw) { + if (pw) + { int i = setuid(pw->pw_uid); - if (i) { + if (i) + { perror("unable to change user"); exit(1); } - } else { + } + else + { //perror("error getting user"); Logger::Log(LOG_ERROR, "unable to get user %s, Is it existing?", username); printf("unable to get user %s, Is it existing?\n", username); @@ -171,16 +190,18 @@ void daemonize() { } pid_t pid = fork(); - if (pid < 0) { + if (pid < 0) + { Logger::Log(LOG_ERROR, "error forking into background"); perror("error forking into background"); - exit(1); /* fork error */ + exit(1); /* fork error */ } - if (pid > 0) { + if (pid > 0) + { // need both here printf("forked into background as pid %d\n", pid); Logger::Log(LOG_INFO, "forked into background as pid %d", pid); - exit(0); /* parent exits */ + exit(0); /* parent exits */ } /* child (daemon) continues */ @@ -190,7 +211,8 @@ void daemonize() { /* obtain a new process group */ pid_t sid = setsid(); - if (sid < 0) { + if (sid < 0) + { perror("unable to get a new session"); exit(1); } @@ -201,71 +223,78 @@ void daemonize() { freopen("/dev/null", "w", stderr); /* Change the current working directory. This prevents the current - directory from being locked; hence not being able to remove it. */ - if ((chdir("/")) < 0) { + * directory from being locked; hence not being able to remove it. */ + if ((chdir("/")) < 0) + { perror("unable to change working directory to /"); exit(1); } /* - // TODO: add config option for lockfile name - { - int lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640); - if (lfp<0) - { - //cannot open - perror("could not open lock file"); - exit(1); - } - if (lockf(lfp,F_TLOCK,0)<0) - { - // cannot lock - perror("could not lock"); - exit(0); - } - - // record pid to lockfile - char str[10]; - sprintf(str,"%d\n",getpid()); - write(lfp,str,strlen(str)); - } - */ + * // TODO: add config option for lockfile name + * { + * int lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640); + * if (lfp<0) + * { + * //cannot open + * perror("could not open lock file"); + * exit(1); + * } + * if (lockf(lfp,F_TLOCK,0)<0) + * { + * // cannot lock + * perror("could not lock"); + * exit(0); + * } + * + * // record pid to lockfile + * char str[10]; + * sprintf(str,"%d\n",getpid()); + * write(lfp,str,strlen(str)); + * } + */ // ignore some signals - signal(SIGCHLD, SIG_IGN); /* ignore child */ - signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ + signal(SIGCHLD, SIG_IGN); /* ignore child */ + signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); } #endif // ! _WIN32 -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ // set default verbose levels Logger::SetLogLevel(LOGTYPE_DISPLAY, LOG_INFO); Logger::SetLogLevel(LOGTYPE_FILE, LOG_VERBOSE); Logger::SetOutputFile("server.log"); - if (!Config::ProcessArgs(argc, argv)) { + if (!Config::ProcessArgs(argc, argv)) return -1; - } - if (Config::GetShowHelp()) { + + if (Config::GetShowHelp()) + { Config::ShowHelp(); return 0; } - if (Config::GetShowVersion()) { + if (Config::GetShowVersion()) + { Config::ShowVersion(); return 0; } // Check configuration ServerType server_mode = Config::getServerMode(); - if (server_mode != SERVER_LAN) { + if (server_mode != SERVER_LAN) + { Logger::Log(LOG_INFO, "Starting server in INET mode"); std::string ip_addr = Config::getIPAddr(); - if (ip_addr.empty() || (ip_addr == "0.0.0.0")) { + if (ip_addr.empty() || (ip_addr == "0.0.0.0")) + { Logger::Log(LOG_WARN, "No IP given, detecting..."); - if (!MasterServer::RetrievePublicIp()) { + if (!MasterServer::RetrievePublicIp()) + { Logger::Log(LOG_ERROR, "Failed to auto-detect public IP, exit."); return -1; } @@ -276,24 +305,27 @@ int main(int argc, char *argv[]) { Logger::Log(LOG_INFO, "Maximum required upload: %ikbit/s", max_clients * (max_clients - 1) * 64); Logger::Log(LOG_INFO, "Maximum required download: %ikbit/s", max_clients * 64); - if (Config::getServerName().empty()) { + if (Config::getServerName().empty()) + { Logger::Log(LOG_ERROR, "Server name not specified, exit."); return -1; } Logger::Log(LOG_INFO, "Server name: %s", Config::getServerName().c_str()); } - if (!Config::checkConfig()) { + if (!Config::checkConfig()) return 1; - } - if (!sha1check()) { + + if (!sha1check()) + { Logger::Log(LOG_ERROR, "sha1 malfunction!"); return -1; } #ifndef _WIN32 - if (!Config::getForeground()) { + if (!Config::getForeground()) + { // no output because of background mode Logger::SetLogLevel(LOGTYPE_DISPLAY, LOG_NONE); daemonize(); @@ -311,34 +343,40 @@ int main(int argc, char *argv[]) { Listener listener(&s_sequencer, Config::getListenPort()); - if (!listener.Initialize()) { + if (!listener.Initialize()) return -1; - } + s_sequencer.Initialize(&listener); - if (!listener.WaitUntilReady()) { - return -1; // Error already logged - } + if (!listener.WaitUntilReady()) + return -1; // Error already logged + // Listener is ready, let's register ourselves on serverlist (which will contact us back to check). - if (server_mode != SERVER_LAN) { + if (server_mode != SERVER_LAN) + { bool registered = s_master_server.Register(); - if (!registered && (server_mode == SERVER_INET)) { + if (!registered && (server_mode == SERVER_INET)) + { Logger::Log(LOG_ERROR, "Failed to register on serverlist. Exit"); listener.Shutdown(); return -1; - } else if (!registered) // server_mode == SERVER_AUTO + } + else if (!registered) // server_mode == SERVER_AUTO { Logger::Log(LOG_WARN, "Failed to register on serverlist, continuing in LAN mode"); server_mode = SERVER_LAN; - } else { + } + else + { Logger::Log(LOG_INFO, "Registration successful"); } } #ifdef WITH_WEBSERVER // start webserver if used - if (Config::getWebserverEnabled()) { + if (Config::getWebserverEnabled()) + { int port = Config::getWebserverPort(); Logger::Log(LOG_INFO, "starting webserver on port %d ...", port); StartWebserver(port, &s_sequencer, s_master_server.IsRegistered(), s_master_server.GetTrustLevel()); @@ -347,9 +385,11 @@ int main(int argc, char *argv[]) { // start the main program loop // if we need to communiate to the master user the notifier routine - if (server_mode != SERVER_LAN) { + if (server_mode != SERVER_LAN) + { //heartbeat - while (!s_exit_requested) { + while (!s_exit_requested) + { Messaging::UpdateMinuteStats(); s_sequencer.UpdateMinuteStats(); @@ -359,36 +399,42 @@ int main(int argc, char *argv[]) { Logger::Log(LOG_VERBOSE, "Sending heartbeat..."); Json::Value user_list(Json::arrayValue); s_sequencer.GetHeartbeatUserList(&user_list); - if (!s_master_server.SendHeatbeat(user_list)) { - unsigned int timeout = Config::GetHeartbeatRetrySeconds(); + if (!s_master_server.SendHeatbeat(user_list)) + { + unsigned int timeout = Config::GetHeartbeatRetrySeconds(); unsigned int max_retries = Config::GetHeartbeatRetryCount(); Logger::Log(LOG_WARN, "A heartbeat failed! Retry in %d seconds.", timeout); - bool success = false; - for (unsigned int i = 0; i < max_retries; ++i) { + bool success = false; + for (unsigned int i = 0; i < max_retries; ++i) + { Utils::SleepSeconds(timeout); success = s_master_server.SendHeatbeat(user_list); - LogLevel log_level = (success ? LOG_INFO : LOG_ERROR); + LogLevel log_level = (success ? LOG_INFO : LOG_ERROR); const char *log_result = (success ? "successful." : "failed."); Logger::Log(log_level, "Heartbeat retry %d/%d %s", i + 1, max_retries, log_result); - if (success) { + if (success) break; - } } - if (!success) { + if (!success) + { Logger::Log(LOG_ERROR, "Unable to send heartbeats, exit"); s_exit_requested = true; } - } else { + } + else + { Logger::Log(LOG_VERBOSE, "Heartbeat sent OK"); } } - if (s_master_server.IsRegistered()) { + if (s_master_server.IsRegistered()) s_master_server.UnRegister(); - } - } else { - while (!s_exit_requested) { + } + else + { + while (!s_exit_requested) + { Messaging::UpdateMinuteStats(); s_sequencer.UpdateMinuteStats(); @@ -398,9 +444,7 @@ int main(int argc, char *argv[]) { // sleep a minute Utils::SleepSeconds(60); } - } - - s_sequencer.Close(); + } s_sequencer.Close(); return 0; } diff --git a/source/server/sequencer.cpp b/source/server/sequencer.cpp index 9d3cdbcd..6fd416ff 100644 --- a/source/server/sequencer.cpp +++ b/source/server/sequencer.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "sequencer.h" @@ -49,20 +49,23 @@ unsigned int Sequencer::connCrash = 0; unsigned int Sequencer::connCount = 0; Client::Client(Sequencer *sequencer, SWInetSocket *socket) : - m_socket(socket), - m_receiver(sequencer), - m_broadcaster(sequencer), - m_status(Client::STATUS_USED), - m_is_receiving_data(false), - m_is_initialized(false) { + m_socket(socket), + m_receiver(sequencer), + m_broadcaster(sequencer), + m_status(Client::STATUS_USED), + m_is_receiving_data(false), + m_is_initialized(false) +{ } -void Client::StartThreads() { +void Client::StartThreads() +{ m_receiver.Start(user.uniqueid, m_socket); m_broadcaster.Start(user.uniqueid, m_socket); } -void Client::Disconnect() { +void Client::Disconnect() +{ // CRITICAL ORDER OF EVENTS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // stop the broadcaster first, then disconnect the socket. // other wise there is a chance (being concurrent code) that the @@ -73,66 +76,74 @@ void Client::Disconnect() { m_broadcaster.Stop(); m_receiver.Stop(); SWBaseSocket::SWBaseError result; - bool disconnected_ok = m_socket->disconnect(&result); - if (!disconnected_ok || (result != SWBaseSocket::base_error::ok)) { + bool disconnected_ok = m_socket->disconnect(&result); + if (!disconnected_ok || (result != SWBaseSocket::base_error::ok)) Logger::Log( - LOG_ERROR, - "Internal: Error while disconnecting client - failed to disconnect socket. Message: %s", - result.get_error().c_str()); - } + LOG_ERROR, + "Internal: Error while disconnecting client - failed to disconnect socket. Message: %s", + result.get_error().c_str()); // END CRITICAL ORDER OF EVENTS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! delete m_socket; } -std::string Client::GetIpAddress() { +std::string Client::GetIpAddress() +{ SWBaseSocket::SWBaseError result; - std::string ip = m_socket->get_peerAddr(&result); - if (result != SWBaseSocket::base_error::ok) { + std::string ip = m_socket->get_peerAddr(&result); + + if (result != SWBaseSocket::base_error::ok) Logger::Log( - LOG_ERROR, - "Internal: Error while getting client IP address. Message: %s", - result.get_error().c_str()); - } + LOG_ERROR, + "Internal: Error while getting client IP address. Message: %s", + result.get_error().c_str()); return ip; } void Client::QueueMessage(int msg_type, int client_id, unsigned int stream_id, unsigned int payload_len, - const char *payload) { + const char *payload) +{ m_broadcaster.QueueMessage(msg_type, client_id, stream_id, payload_len, payload); } // Yes, this is weird. To be refactored. -void Client::NotifyAllVehicles(Sequencer *sequencer) { - if (!m_is_initialized) { +void Client::NotifyAllVehicles(Sequencer *sequencer) +{ + if (!m_is_initialized) + { sequencer->IntroduceNewClientToAllVehicles(this); m_is_initialized = true; } } -void *LaunchKillerThread(void *data) { +void *LaunchKillerThread(void *data) +{ Sequencer *sequencer = static_cast(data); + sequencer->killerthreadstart(); return nullptr; } Sequencer::Sequencer() : - m_listener(nullptr), - m_script_engine(nullptr), - m_auth_resolver(nullptr), - m_bot_count(0), - m_free_user_id(1) { + m_listener(nullptr), + m_script_engine(nullptr), + m_auth_resolver(nullptr), + m_bot_count(0), + m_free_user_id(1) +{ m_start_time = static_cast(time(nullptr)); } /** * Inililize, needs to be called before the class is used */ -void Sequencer::Initialize(Listener *listener) { +void Sequencer::Initialize(Listener *listener) +{ m_listener = listener; m_clients.reserve(Config::getMaxClients()); #ifdef WITH_ANGELSCRIPT - if (Config::getEnableScripting()) { + if (Config::getEnableScripting()) + { m_script_engine = new ScriptEngine(this); m_script_engine->loadScript(Config::getScriptName()); } @@ -145,15 +156,20 @@ void Sequencer::Initialize(Listener *listener) { * Cleanup function is to be called when the Sequencer is done being used * this is in place of the destructor. */ -void Sequencer::Close() { +void Sequencer::Close() +{ static bool cleanup = false; - if (cleanup) return; - cleanup = true; // WTF?? ~ only_a_ptr, 05/2016 + + if (cleanup) + return; + + cleanup = true; // WTF?? ~ only_a_ptr, 05/2016 Logger::Log(LOG_INFO, "closing. disconnecting clients ..."); const char *str = "server shutting down (try to reconnect later!)"; - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { // HACK-ISH override all thread stuff and directly send it! Client *client = m_clients[i]; Messaging::SendMessage(client->GetSocket(), RoRnet::MSG2_USER_LEAVE, client->user.uniqueid, 0, strlen(str), @@ -162,77 +178,87 @@ void Sequencer::Close() { Logger::Log(LOG_INFO, "all clients disconnected. exiting."); #ifdef WITH_ANGELSCRIPT - if (m_script_engine != nullptr) { + if (m_script_engine != nullptr) + { delete m_script_engine; m_script_engine = nullptr; } #endif //WITH_ANGELSCRIPT - if (m_auth_resolver != nullptr) { + if (m_auth_resolver != nullptr) + { delete m_auth_resolver; m_auth_resolver = nullptr; } - if (m_listener != nullptr) { + if (m_listener != nullptr) + { delete m_listener; m_listener = nullptr; } pthread_cancel(m_killer_thread); pthread_detach(m_killer_thread); - cleanup = false; // WTF?? ~ only_a_ptr, 05/2016 + cleanup = false; // WTF?? ~ only_a_ptr, 05/2016 } -bool Sequencer::CheckNickIsUnique(std::string &nick) { +bool Sequencer::CheckNickIsUnique(std::string &nick) +{ // WARNING: be sure that this is only called within a clients_mutex lock! // check for duplicate names - for (unsigned int i = 0; i < m_clients.size(); i++) { - if (nick == Str::SanitizeUtf8(m_clients[i]->user.username)) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { + if (nick == Str::SanitizeUtf8(m_clients[i]->user.username)) return true; - } } return false; } -int Sequencer::GetFreePlayerColour() { +int Sequencer::GetFreePlayerColour() +{ // WARNING: be sure that this is only called within a clients_mutex lock! int col = 0; - for (;;) // TODO: How many colors ARE there? + + for (;; ) // TODO: How many colors ARE there? { bool collision = false; - for (unsigned int i = 0; i < m_clients.size(); i++) { - if (m_clients[i]->user.colournum == col) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { + if (m_clients[i]->user.colournum == col) + { collision = true; break; } } - if (!collision) { + if (!collision) return col; - } + col++; } } //this is called by the Listener thread -void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { +void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) +{ //we have a confirmed client that wants to play //try to find a place for him Logger::Log(LOG_DEBUG, "got instance in createClient()"); MutexLocker scoped_lock(m_clients_mutex); - std::string nick = Str::SanitizeUtf8(user.username); - bool dupeNick = Sequencer::CheckNickIsUnique(nick); - int playerColour = Sequencer::GetFreePlayerColour(); + std::string nick = Str::SanitizeUtf8(user.username); + bool dupeNick = Sequencer::CheckNickIsUnique(nick); + int playerColour = Sequencer::GetFreePlayerColour(); - int dupecounter = 2; + int dupecounter = 2; // check if banned SWBaseSocket::SWBaseError error; - if (Sequencer::IsBanned(sock->get_peerAddr(&error).c_str())) { + if (Sequencer::IsBanned(sock->get_peerAddr(&error).c_str())) + { Logger::Log(LOG_VERBOSE, "rejected banned IP %s", sock->get_peerAddr(&error).c_str()); Messaging::SendMessage(sock, RoRnet::MSG2_BANNED, 0, 0, 0, 0); return; @@ -240,7 +266,8 @@ void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { // check if server is full Logger::Log(LOG_DEBUG, "searching free slot for new client..."); - if (m_clients.size() >= (Config::getMaxClients() + m_bot_count)) { + if (m_clients.size() >= (Config::getMaxClients() + m_bot_count)) + { Logger::Log(LOG_WARN, "join request from '%s' on full server: rejecting!", Str::SanitizeUtf8(user.username).c_str()); // set a low time out because we don't want to cause a back up of @@ -250,16 +277,18 @@ void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { throw std::runtime_error("Server is full"); } - if (dupeNick) { + if (dupeNick) + { Logger::Log(LOG_WARN, std::string("found duplicate nick, getting new one: ") + nick); // shorten username so the number will fit (only if its too long already) std::string new_nick_base = nick.substr(0, RORNET_MAX_USERNAME_LEN - 4); // now get a new number - while (dupeNick) { + while (dupeNick) + { char buf[20] = ""; sprintf(buf, "_%3d", dupecounter++); - nick = new_nick_base + buf; + nick = new_nick_base + buf; dupeNick = Sequencer::CheckNickIsUnique(nick); } Logger::Log(LOG_WARN, std::string("New username was composed: ") + nick); @@ -275,8 +304,8 @@ void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { //okay, create the client slot Client *to_add = new Client(this, sock); - to_add->user = user; - to_add->user.colournum = playerColour; + to_add->user = user; + to_add->user.colournum = playerColour; to_add->user.authstatus = user.authstatus; // log some info about this client (in UTF8) @@ -304,16 +333,16 @@ void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { Logger::Log(LOG_VERBOSE, "Sending welcome message to uid %i", client_id); if (Messaging::SendMessage(sock, RoRnet::MSG2_WELCOME, client_id, 0, sizeof(RoRnet::UserInfo), - (char *) &to_add->user)) { + (char*)&to_add->user)) + { Sequencer::disconnect(client_id, "error sending welcome message"); return; } // Do script callback #ifdef WITH_ANGELSCRIPT - if (m_script_engine != nullptr) { + if (m_script_engine != nullptr) m_script_engine->playerAdded(client_id); - } #endif //WITH_ANGELSCRIPT // notify everyone of the new client @@ -321,9 +350,10 @@ void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { RoRnet::UserInfo info_for_others = to_add->user; memset(info_for_others.usertoken, 0, 40); memset(info_for_others.clientGUID, 0, 40); - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { m_clients[i]->QueueMessage(RoRnet::MSG2_USER_JOIN, client_id, 0, sizeof(RoRnet::UserInfo), - (char *) &info_for_others); + (char*)&info_for_others); } // done! @@ -331,63 +361,76 @@ void Sequencer::createClient(SWInetSocket *sock, RoRnet::UserInfo user) { } // assuming client lock -void Sequencer::broadcastUserInfo(int client_id) { +void Sequencer::broadcastUserInfo(int client_id) +{ Client *client = this->FindClientById(static_cast(client_id)); - if (client == nullptr) { + + if (client == nullptr) return; - } + // notify everyone of the client // but blank out the user token and GUID RoRnet::UserInfo info_for_others = client->user; memset(info_for_others.usertoken, 0, 40); memset(info_for_others.clientGUID, 0, 40); - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { m_clients[i]->QueueMessage(RoRnet::MSG2_USER_INFO, info_for_others.uniqueid, 0, sizeof(RoRnet::UserInfo), - (char *) &info_for_others); + (char*)&info_for_others); } } -void Sequencer::GetHeartbeatUserList(Json::Value *out_array) { +void Sequencer::GetHeartbeatUserList(Json::Value *out_array) +{ MutexLocker scoped_lock(m_clients_mutex); - auto itor = m_clients.begin(); - auto endi = m_clients.end(); - for (; itor != endi; ++itor) { - Client *client = *itor; + auto itor = m_clients.begin(); + auto endi = m_clients.end(); + + for (; itor != endi; ++itor) + { + Client *client = *itor; Json::Value user_data(Json::objectValue); - user_data["is_admin"] = (client->user.authstatus & RoRnet::AUTH_ADMIN); - user_data["is_mod"] = (client->user.authstatus & RoRnet::AUTH_MOD); - user_data["is_ranked"] = (client->user.authstatus & RoRnet::AUTH_RANKED); - user_data["is_bot"] = (client->user.authstatus & RoRnet::AUTH_BOT); - user_data["username"] = client->user.username; + user_data["is_admin"] = (client->user.authstatus & RoRnet::AUTH_ADMIN); + user_data["is_mod"] = (client->user.authstatus & RoRnet::AUTH_MOD); + user_data["is_ranked"] = (client->user.authstatus & RoRnet::AUTH_RANKED); + user_data["is_bot"] = (client->user.authstatus & RoRnet::AUTH_BOT); + user_data["username"] = client->user.username; user_data["ip_address"] = client->GetIpAddress(); - user_data["client_id"] = client->user.uniqueid; + user_data["client_id"] = client->user.uniqueid; out_array->append(user_data); } } -int Sequencer::getNumClients() { +int Sequencer::getNumClients() +{ MutexLocker scoped_lock(m_clients_mutex); - return (int) m_clients.size(); + + return (int)m_clients.size(); } -int Sequencer::AuthorizeNick(std::string token, std::string &nickname) { +int Sequencer::AuthorizeNick(std::string token, std::string &nickname) +{ MutexLocker scoped_lock(m_clients_mutex); - if (m_auth_resolver == nullptr) { + + if (m_auth_resolver == nullptr) return RoRnet::AUTH_NONE; - } + return m_auth_resolver->resolve(token, nickname, m_free_user_id); } -void Sequencer::killerthreadstart() { +void Sequencer::killerthreadstart() +{ Logger::Log(LOG_DEBUG, "Killer thread ready"); - while (1) { + while (1) + { Logger::Log(LOG_DEBUG, "Killer entering cycle"); m_killer_mutex.lock(); - while (m_kill_queue.empty()) { + while (m_kill_queue.empty()) + { m_killer_mutex.wait(m_killer_cond); } @@ -404,29 +447,28 @@ void Sequencer::killerthreadstart() { } } -void Sequencer::disconnect(int uid, const char *errormsg, bool isError, bool doScriptCallback /*= true*/) { +void Sequencer::disconnect(int uid, const char *errormsg, bool isError, bool doScriptCallback /*= true*/) +{ MutexLocker scoped_lock(m_killer_mutex); - Client *client = this->FindClientById(static_cast(uid)); - if (client == nullptr) { + Client *client = this->FindClientById(static_cast(uid)); + + if (client == nullptr) return; - } + // send an event if user is rankend and if we are a official server - if (m_auth_resolver && (client->user.authstatus & RoRnet::AUTH_RANKED)) { + if (m_auth_resolver && (client->user.authstatus & RoRnet::AUTH_RANKED)) m_auth_resolver->sendUserEvent(client->user.usertoken, (isError ? "crash" : "leave"), Str::SanitizeUtf8(client->user.username), ""); - } #ifdef WITH_ANGELSCRIPT - if (m_script_engine != nullptr && doScriptCallback) { + if (m_script_engine != nullptr && doScriptCallback) m_script_engine->playerDeleted(client->user.uniqueid, isError ? 1 : 0); - } #endif //WITH_ANGELSCRIPT // Update the botCount value - if ((client->user.authstatus & RoRnet::AUTH_BOT) > 0) { + if ((client->user.authstatus & RoRnet::AUTH_BOT) > 0) m_bot_count--; - } //this routine is a potential trouble maker as it can be called from many thread contexts //so we use a killer thread @@ -436,33 +478,34 @@ void Sequencer::disconnect(int uid, const char *errormsg, bool isError, bool doS //notify the others int pos = 0; - for (unsigned int i = 0; i < m_clients.size(); i++) { - m_clients[i]->QueueMessage(RoRnet::MSG2_USER_LEAVE, client->user.uniqueid, 0, (int) strlen(errormsg), errormsg); - if (m_clients[i]->user.uniqueid == static_cast(uid)) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { + m_clients[i]->QueueMessage(RoRnet::MSG2_USER_LEAVE, client->user.uniqueid, 0, (int)strlen(errormsg), errormsg); + if (m_clients[i]->user.uniqueid == static_cast(uid)) pos = i; - } } m_clients.erase(m_clients.begin() + pos); m_killer_cond.signal(); this->connCount++; - if (isError) { + if (isError) this->connCrash++; - } Logger::Log(LOG_INFO, "crash statistic: %d of %d deletes crashed", this->connCrash, this->connCount); printStats(); } //this is called from the listener thread initial handshake -void Sequencer::enableFlow(int uid) { +void Sequencer::enableFlow(int uid) +{ MutexLocker scoped_lock(m_clients_mutex); - Client *client = this->FindClientById(static_cast(uid)); - if (client == nullptr) { + Client *client = this->FindClientById(static_cast(uid)); + + if (client == nullptr) return; - } + client->SetReceiveData(true); // now they are a bonified part of the server, show the new stats @@ -471,131 +514,150 @@ void Sequencer::enableFlow(int uid) { //this is called from the listener thread initial handshake -int Sequencer::sendMOTD(int uid) { +int Sequencer::sendMOTD(int uid) +{ std::vector lines; - int res = Utils::ReadLinesFromFile(Config::getMOTDFile(), lines); + int res = Utils::ReadLinesFromFile(Config::getMOTDFile(), lines); if (res) return res; std::vector::iterator it; - for (it = lines.begin(); it != lines.end(); it++) { + for (it = lines.begin(); it != lines.end(); it++) + { serverSay(*it, uid, FROM_MOTD); } return 0; } -UserAuth *Sequencer::getUserAuth() { +UserAuth *Sequencer::getUserAuth() +{ return m_auth_resolver; } //this is called from the listener thread initial handshake -void Sequencer::IntroduceNewClientToAllVehicles(Client *new_client) { +void Sequencer::IntroduceNewClientToAllVehicles(Client *new_client) +{ RoRnet::UserInfo info_for_others = new_client->user; + memset(info_for_others.usertoken, 0, 40); memset(info_for_others.clientGUID, 0, 40); - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { Client *client = m_clients[i]; - if (client->GetStatus() == Client::STATUS_USED) { + if (client->GetStatus() == Client::STATUS_USED) + { // new user to all others client->QueueMessage(RoRnet::MSG2_USER_INFO, new_client->user.uniqueid, 0, sizeof(RoRnet::UserInfo), - (char *) &info_for_others); + (char*)&info_for_others); // all others to new user RoRnet::UserInfo info_for_newcomer = m_clients[i]->user; memset(info_for_newcomer.usertoken, 0, 40); memset(info_for_newcomer.clientGUID, 0, 40); new_client->QueueMessage(RoRnet::MSG2_USER_INFO, client->user.uniqueid, 0, sizeof(RoRnet::UserInfo), - (char *) &info_for_newcomer); + (char*)&info_for_newcomer); Logger::Log(LOG_VERBOSE, " * %d streams registered for user %d", m_clients[i]->streams.size(), m_clients[i]->user.uniqueid); auto itor = client->streams.begin(); auto endi = client->streams.end(); - for (; itor != endi; ++itor) { + for (; itor != endi; ++itor) + { Logger::Log(LOG_VERBOSE, "sending stream registration %d:%d to user %d", client->user.uniqueid, itor->first, new_client->user.uniqueid); new_client->QueueMessage(RoRnet::MSG2_STREAM_REGISTER, client->user.uniqueid, itor->first, - sizeof(RoRnet::StreamRegister), (char *) &itor->second); + sizeof(RoRnet::StreamRegister), (char*)&itor->second); } } } } -int Sequencer::sendGameCommand(int uid, std::string cmd) { +int Sequencer::sendGameCommand(int uid, std::string cmd) +{ const char *data = cmd.c_str(); - int size = cmd.size(); + int size = cmd.size(); - if (uid == TO_ALL) { - for (int i = 0; i < (int) m_clients.size(); i++) { + if (uid == TO_ALL) + { + for (int i = 0; i < (int)m_clients.size(); i++) + { m_clients[i]->QueueMessage(RoRnet::MSG2_GAME_CMD, -1, 0, size, data); } - } else { + } + else + { Client *client = this->FindClientById(static_cast(uid)); - if (client != nullptr) { - client->QueueMessage(RoRnet::MSG2_GAME_CMD, -1, 0, size, data); // ClientId -1: comes from the server - } + if (client != nullptr) + client->QueueMessage(RoRnet::MSG2_GAME_CMD, -1, 0, size, data); // ClientId -1: comes from the server } return 0; } // this does not lock the clients_mutex, make sure it is locked before hand // note: uid==-1==TO_ALL = broadcast your message to all players -void Sequencer::serverSay(std::string msg, int uid, int type) { - switch (type) { - case FROM_SERVER: - msg = std::string("SERVER: ") + msg; - break; - - case FROM_HOST: - if (uid == -1) { - msg = std::string("Host(general): ") + msg; - } else { - msg = std::string("Host(private): ") + msg; - } - break; - - case FROM_RULES: - msg = std::string("Rules: ") + msg; - break; - - case FROM_MOTD: - msg = std::string("MOTD: ") + msg; - break; +void Sequencer::serverSay(std::string msg, int uid, int type) +{ + switch (type) + { + case FROM_SERVER: + msg = std::string("SERVER: ") + msg; + break; + + case FROM_HOST: + if (uid == -1) + msg = std::string("Host(general): ") + msg; + else + msg = std::string("Host(private): ") + msg; + break; + + case FROM_RULES: + msg = std::string("Rules: ") + msg; + break; + + case FROM_MOTD: + msg = std::string("MOTD: ") + msg; + break; } auto itor = m_clients.begin(); auto endi = m_clients.end(); - for (; itor != endi; ++itor) { + for (; itor != endi; ++itor) + { Client *client = *itor; if ((client->GetStatus() == Client::STATUS_USED) && client->IsReceivingData() && - (uid == TO_ALL || ((int) client->user.uniqueid) == uid)) { + (uid == TO_ALL || ((int)client->user.uniqueid) == uid)) + { std::string msg_valid = Str::SanitizeUtf8(msg.begin(), msg.end()); client->QueueMessage(RoRnet::MSG2_UTF8_CHAT, -1, -1, msg_valid.length(), msg_valid.c_str()); } } } -void Sequencer::serverSayThreadSave(std::string msg, int uid, int type) { +void Sequencer::serverSayThreadSave(std::string msg, int uid, int type) +{ this->serverSay(msg, uid, type); } -bool Sequencer::Kick(int kuid, int modUID, const char *msg) { +bool Sequencer::Kick(int kuid, int modUID, const char *msg) +{ Client *kicked_client = this->FindClientById(static_cast(kuid)); - if (kicked_client == nullptr) { + + if (kicked_client == nullptr) return false; - } + Client *mod_client = this->FindClientById(static_cast(modUID)); - if (mod_client == nullptr) { + if (mod_client == nullptr) return false; - } + char kickmsg[1024] = ""; strcat(kickmsg, "kicked by "); strcat(kickmsg, Str::SanitizeUtf8(mod_client->user.username).c_str()); - if (msg) { + if (msg) + { strcat(kickmsg, " for "); strcat(kickmsg, msg); } @@ -605,31 +667,34 @@ bool Sequencer::Kick(int kuid, int modUID, const char *msg) { serverSay(kickmsg2, TO_ALL, FROM_SERVER); Logger::Log( - LOG_VERBOSE, - "player '%s' kicked by '%s'", - Str::SanitizeUtf8(kicked_client->user.username).c_str(), - Str::SanitizeUtf8(mod_client->user.username).c_str()); + LOG_VERBOSE, + "player '%s' kicked by '%s'", + Str::SanitizeUtf8(kicked_client->user.username).c_str(), + Str::SanitizeUtf8(mod_client->user.username).c_str()); disconnect(kicked_client->user.uniqueid, kickmsg); return true; } -bool Sequencer::Ban(int buid, int modUID, const char *msg) { +bool Sequencer::Ban(int buid, int modUID, const char *msg) +{ Client *banned_client = this->FindClientById(static_cast(buid)); - if (banned_client == nullptr) { + + if (banned_client == nullptr) return false; - } + Client *mod_client = this->FindClientById(static_cast(modUID)); - if (mod_client == nullptr) { + if (mod_client == nullptr) return false; - } + // construct ban data and add it to the list ban_t *b = new ban_t; memset(b, 0, sizeof(ban_t)); b->uid = buid; - if (msg) strncpy(b->banmsg, msg, 256); + if (msg) + strncpy(b->banmsg, msg, 256); std::string mod_nickname = Str::SanitizeUtf8(mod_client->user.username); strncpy(b->bannedby_nick, mod_nickname.c_str(), RORNET_MAX_USERNAME_LEN); strncpy(b->ip, banned_client->GetIpAddress().c_str(), 16); @@ -640,17 +705,19 @@ bool Sequencer::Ban(int buid, int modUID, const char *msg) { Logger::Log(LOG_VERBOSE, "new ban added: '%s' by '%s'", banned_nickname.c_str(), mod_nickname.c_str()); char tmp[1024] = ""; - if (msg) { + if (msg) strcat(tmp, msg); - } strcat(tmp, " (banned)"); return Kick(buid, modUID, tmp); } -void Sequencer::SilentBan(int buid, const char *msg, bool doScriptCallback /*= true*/) { +void Sequencer::SilentBan(int buid, const char *msg, bool doScriptCallback /*= true*/) +{ Client *banned_client = this->FindClientById(static_cast(buid)); - if (banned_client == nullptr) { + + if (banned_client == nullptr) + { Logger::Log(LOG_ERROR, "void Sequencer::ban(%d, %s) --> uid %d not found!", buid, msg, buid); return; } @@ -660,7 +727,8 @@ void Sequencer::SilentBan(int buid, const char *msg, bool doScriptCallback /*= t memset(b, 0, sizeof(ban_t)); b->uid = buid; - if (msg) strncpy(b->banmsg, msg, 256); + if (msg) + strncpy(b->banmsg, msg, 256); strncpy(b->bannedby_nick, "rorserver", RORNET_MAX_USERNAME_LEN); strncpy(b->ip, banned_client->GetIpAddress().c_str(), 16); std::string banned_nickname = Str::SanitizeUtf8(banned_client->user.username); @@ -670,17 +738,19 @@ void Sequencer::SilentBan(int buid, const char *msg, bool doScriptCallback /*= t Logger::Log(LOG_VERBOSE, "new ban added '%s' by rorserver", banned_nickname.c_str()); char tmp[1024] = ""; - if (msg) { + if (msg) strcat(tmp, msg); - } strcat(tmp, " (banned)"); disconnect(banned_client->user.uniqueid, tmp, false, doScriptCallback); } -bool Sequencer::UnBan(int buid) { - for (unsigned int i = 0; i < m_bans.size(); i++) { - if (((int) m_bans[i]->uid) == buid) { +bool Sequencer::UnBan(int buid) +{ + for (unsigned int i = 0; i < m_bans.size(); i++) + { + if (((int)m_bans[i]->uid) == buid) + { m_bans.erase(m_bans.begin() + i); Logger::Log(LOG_VERBOSE, "uid unbanned: %d", buid); return true; @@ -689,30 +759,36 @@ bool Sequencer::UnBan(int buid) { return false; } -bool Sequencer::IsBanned(const char *ip) { - if (ip == nullptr) { +bool Sequencer::IsBanned(const char *ip) +{ + if (ip == nullptr) return false; - } - for (unsigned int i = 0; i < m_bans.size(); i++) { + + for (unsigned int i = 0; i < m_bans.size(); i++) + { if (!strcmp(m_bans[i]->ip, ip)) return true; } return false; } -void Sequencer::streamDebug() { - for (unsigned int i = 0; i < m_clients.size(); i++) { - if (m_clients[i]->GetStatus() == Client::STATUS_USED) { +void Sequencer::streamDebug() +{ + for (unsigned int i = 0; i < m_clients.size(); i++) + { + if (m_clients[i]->GetStatus() == Client::STATUS_USED) + { Logger::Log(LOG_VERBOSE, " * %d %s (slot %d):", m_clients[i]->user.uniqueid, Str::SanitizeUtf8(m_clients[i]->user.username).c_str(), i); if (!m_clients[i]->streams.size()) Logger::Log(LOG_VERBOSE, " * no streams registered for user %d", m_clients[i]->user.uniqueid); else for (std::map::iterator it = m_clients[i]->streams.begin(); - it != m_clients[i]->streams.end(); it++) { - char *types[] = {(char *) "truck", (char *) "character", (char *) "aitraffic", (char *) "chat"}; - char *typeStr = (char *) "unkown"; + it != m_clients[i]->streams.end(); it++) + { + char *types[] = { (char*)"truck", (char*)"character", (char*)"aitraffic", (char*)"chat" }; + char *typeStr = (char*)"unkown"; if (it->second.type >= 0 && it->second.type <= 3) typeStr = types[it->second.type]; Logger::Log(LOG_VERBOSE, " * %d:%d, type:%s status:%d name:'%s'", m_clients[i]->user.uniqueid, @@ -723,33 +799,39 @@ void Sequencer::streamDebug() { } //this is called by the receivers threads, like crazy & concurrently -void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *data, unsigned int len) { +void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *data, unsigned int len) +{ MutexLocker scoped_lock(m_clients_mutex); - Client *client = this->FindClientById(static_cast(uid)); - if (client == nullptr) { + Client *client = this->FindClientById(static_cast(uid)); + + if (client == nullptr) return; - } + // check for full broadcaster queue { bool is_dropping = client->IsBroadcasterDroppingPackets(); - if (is_dropping && client->drop_state == 0) { + if (is_dropping && client->drop_state == 0) + { // queue full, inform client int drop_state = 1; client->drop_state = drop_state; - client->QueueMessage(RoRnet::MSG2_NETQUALITY, -1, 0, sizeof(int), (char *) &drop_state); - } else if (!is_dropping && client->drop_state == 1) { + client->QueueMessage(RoRnet::MSG2_NETQUALITY, -1, 0, sizeof(int), (char*)&drop_state); + } + else if (!is_dropping && client->drop_state == 1) + { // queue working better again, inform client int drop_state = 0; client->drop_state = drop_state; - client->QueueMessage(RoRnet::MSG2_NETQUALITY, -1, 0, sizeof(int), (char *) &drop_state); + client->QueueMessage(RoRnet::MSG2_NETQUALITY, -1, 0, sizeof(int), (char*)&drop_state); } } int publishMode = BROADCAST_BLOCK; - if (type == RoRnet::MSG2_STREAM_DATA) { + if (type == RoRnet::MSG2_STREAM_DATA) + { client->NotifyAllVehicles(this); publishMode = BROADCAST_NORMAL; @@ -758,15 +840,21 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat { std::map::iterator it = client->streams.find(streamid); if (it == client->streams.end()) + { publishMode = BROADCAST_BLOCK; - else if (it->second.type == 0) { - RoRnet::TruckStreamRegister *reg = (RoRnet::TruckStreamRegister *) &it->second; - if ((unsigned int) reg->bufferSize + sizeof(RoRnet::TruckState) != len) + } + else if (it->second.type == 0) + { + RoRnet::TruckStreamRegister *reg = (RoRnet::TruckStreamRegister*)&it->second; + if ((unsigned int)reg->bufferSize + sizeof(RoRnet::TruckState) != len) publishMode = BROADCAST_BLOCK; } } - } else if (type == RoRnet::MSG2_STREAM_REGISTER) { - if (client->streams.size() >= Config::getMaxVehicles() + NON_VEHICLE_STREAMS) { + } + else if (type == RoRnet::MSG2_STREAM_REGISTER) + { + if (client->streams.size() >= Config::getMaxVehicles() + NON_VEHICLE_STREAMS) + { // This user has too many vehicles, we drop the stream and then disconnect the user Logger::Log(LOG_INFO, "%s(%d) has too many streams. Stream dropped, user kicked.", Str::SanitizeUtf8(client->user.username).c_str(), client->user.uniqueid); @@ -781,42 +869,51 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat Str::SanitizeUtf8(client->user.username).c_str(), Config::getMaxVehicles()); serverSay(sayMsg, TO_ALL, FROM_SERVER); disconnect(client->user.uniqueid, "You have too many vehicles. Please rejoin.", false); - publishMode = BROADCAST_BLOCK; // drop - } else { + publishMode = BROADCAST_BLOCK; // drop + } + else + { publishMode = BROADCAST_NORMAL; - RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *) data; + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister*)data; #ifdef WITH_ANGELSCRIPT // Do a script callback - if (m_script_engine) { + if (m_script_engine) + { int scriptpub = m_script_engine->streamAdded(client->user.uniqueid, reg); // We only support blocking and normal at the moment. Other modes are not supported. - switch (scriptpub) { - case BROADCAST_AUTO: - break; + switch (scriptpub) + { + case BROADCAST_AUTO: + break; - case BROADCAST_BLOCK: - publishMode = BROADCAST_BLOCK; - break; + case BROADCAST_BLOCK: + publishMode = BROADCAST_BLOCK; + break; - case BROADCAST_NORMAL: - publishMode = BROADCAST_NORMAL; - break; + case BROADCAST_NORMAL: + publishMode = BROADCAST_NORMAL; + break; - default: - Logger::Log(LOG_ERROR, "Stream broadcasting mode not supported."); - break; + default: + Logger::Log(LOG_ERROR, "Stream broadcasting mode not supported."); + break; } } -#endif //WITH_ANGELSCRIPT +#endif //WITH_ANGELSCRIPT - if (publishMode != BROADCAST_BLOCK) { + if (publishMode != BROADCAST_BLOCK) + { // Add the stream Logger::Log(LOG_VERBOSE, " * new stream registered: %d:%d, type: %d, name: '%s', status: %d", client->user.uniqueid, streamid, reg->type, reg->name, reg->status); - for (int i = 0; i < 128; i++) if (reg->name[i] == ' ') reg->name[i] = 0; // convert spaces to zero's - reg->name[127] = 0; + for (int i = 0; i < 128; i++) + { + if (reg->name[i] == ' ') + reg->name[i] = 0; // convert spaces to zero's + } + reg->name[127] = 0; client->streams[streamid] = *reg; // send an event if user is rankend and if we are a official server @@ -826,7 +923,8 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat // Notify the user about the vehicle limit if ((client->streams.size() >= Config::getMaxVehicles() + NON_VEHICLE_STREAMS - 3) && - (client->streams.size() > NON_VEHICLE_STREAMS)) { + (client->streams.size() > NON_VEHICLE_STREAMS)) + { // we start warning the user as soon as he has only 3 vehicles left before he will get kicked (that's why we do minus three in the 'if' statement above). char sayMsg[128] = ""; @@ -845,31 +943,39 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat // reset some stats // streams_traffic limited through streams map - client->streams_traffic[streamid].bandwidthIncoming = 0; + client->streams_traffic[streamid].bandwidthIncoming = 0; client->streams_traffic[streamid].bandwidthIncomingLastMinute = 0; - client->streams_traffic[streamid].bandwidthIncomingRate = 0; - client->streams_traffic[streamid].bandwidthOutgoing = 0; + client->streams_traffic[streamid].bandwidthIncomingRate = 0; + client->streams_traffic[streamid].bandwidthOutgoing = 0; client->streams_traffic[streamid].bandwidthOutgoingLastMinute = 0; - client->streams_traffic[streamid].bandwidthOutgoingRate = 0; + client->streams_traffic[streamid].bandwidthOutgoingRate = 0; } } - } else if (type == RoRnet::MSG2_STREAM_REGISTER_RESULT) { + } + else if (type == RoRnet::MSG2_STREAM_REGISTER_RESULT) + { // forward message to the stream origin - RoRnet::StreamRegister *reg = (RoRnet::StreamRegister *) data; - Client *origin_client = this->FindClientById(reg->origin_sourceid); - if (origin_client != nullptr) { - origin_client->QueueMessage(type, uid, 0, sizeof(RoRnet::StreamRegister), (char *) reg); + RoRnet::StreamRegister *reg = (RoRnet::StreamRegister*)data; + Client *origin_client = this->FindClientById(reg->origin_sourceid); + if (origin_client != nullptr) + { + origin_client->QueueMessage(type, uid, 0, sizeof(RoRnet::StreamRegister), (char*)reg); Logger::Log(LOG_VERBOSE, "stream registration result for stream %03d:%03d from user %03d: %d", reg->origin_sourceid, reg->origin_streamid, uid, reg->status); } publishMode = BROADCAST_BLOCK; - } else if (type == RoRnet::MSG2_STREAM_UNREGISTER) { + } + else if (type == RoRnet::MSG2_STREAM_UNREGISTER) + { // Remove the stream - if (client->streams.erase(streamid) > 0) { + if (client->streams.erase(streamid) > 0) + { Logger::Log(LOG_VERBOSE, " * stream deregistered: %d:%d", client->user.uniqueid, streamid); publishMode = BROADCAST_ALL; } - } else if (type == RoRnet::MSG2_USER_LEAVE) { + } + else if (type == RoRnet::MSG2_USER_LEAVE) + { // from client Logger::Log(LOG_INFO, "User disconnects on request: " + Str::SanitizeUtf8(client->user.username)); @@ -877,48 +983,66 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat //sprintf(tmp, "user %s disconnects on request", UTF8BuffertoString(client->user.username).c_str()); //serverSay(std::string(tmp), -1); disconnect(client->user.uniqueid, "disconnected on request", false); - } else if (type == RoRnet::MSG2_UTF8_CHAT) { + } + else if (type == RoRnet::MSG2_UTF8_CHAT) + { std::string str = Str::SanitizeUtf8(data); Logger::Log(LOG_INFO, "CHAT| %s: %s", Str::SanitizeUtf8(client->user.username).c_str(), str); publishMode = BROADCAST_ALL; // no broadcast of server commands! - if (str[0] == '!') publishMode = BROADCAST_BLOCK; + if (str[0] == '!') + publishMode = BROADCAST_BLOCK; #ifdef WITH_ANGELSCRIPT - if (m_script_engine) { + if (m_script_engine) + { int scriptpub = m_script_engine->playerChat(client->user.uniqueid, str); - if (scriptpub != BROADCAST_AUTO) publishMode = scriptpub; + if (scriptpub != BROADCAST_AUTO) + publishMode = scriptpub; } -#endif //WITH_ANGELSCRIPT - if (str == "!help") { +#endif //WITH_ANGELSCRIPT + if (str == "!help") + { serverSay(std::string("builtin commands:"), uid); serverSay(std::string("!version, !list, !say, !bans, !ban, !unban, !kick, !vehiclelimit"), uid); serverSay(std::string("!website, !irc, !owner, !voip, !rules, !motd"), uid); } - if (str == "!version") { + if (str == "!version") + { serverSay(std::string(VERSION), uid); - } else if (str == "!list") { + } + else if (str == "!list") + { serverSay(std::string(" uid | auth | nick"), uid); - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { if (i >= m_clients.size()) break; char authst[10] = ""; - if (m_clients[i]->user.authstatus & RoRnet::AUTH_ADMIN) strcat(authst, "A"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_MOD) strcat(authst, "M"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_RANKED) strcat(authst, "R"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_BOT) strcat(authst, "B"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_BANNED) strcat(authst, "X");\ + if (m_clients[i]->user.authstatus & RoRnet::AUTH_ADMIN) + strcat(authst, "A"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_MOD) + strcat(authst, "M"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_RANKED) + strcat(authst, "R"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_BOT) + strcat(authst, "B"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_BANNED) + strcat(authst, "X"); \ char tmp2[256] = ""; sprintf(tmp2, "% 3d | %-6s | %-20s", m_clients[i]->user.uniqueid, authst, Str::SanitizeUtf8(m_clients[i]->user.username).c_str()); serverSay(std::string(tmp2), uid); } - } else if (str.substr(0, 5) == "!bans") { + } + else if (str.substr(0, 5) == "!bans") + { serverSay(std::string("uid | IP | nickname | banned by"), uid); - for (unsigned int i = 0; i < m_bans.size(); i++) { + for (unsigned int i = 0; i < m_bans.size(); i++) + { char tmp[256] = ""; sprintf(tmp, "% 3d | %-15s | %-20s | %-20s", m_bans[i]->uid, @@ -927,196 +1051,262 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat m_bans[i]->bannedby_nick); serverSay(std::string(tmp), uid); } - } else if (str.substr(0, 7) == "!unban ") { - if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) { + } + else if (str.substr(0, 7) == "!unban ") + { + if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) + { int buid = -1; - int res = sscanf(str.substr(7).c_str(), "%d", &buid); - if (res != 1 || buid == -1) { + int res = sscanf(str.substr(7).c_str(), "%d", &buid); + if (res != 1 || buid == -1) + { serverSay(std::string("usage: !unban "), uid); serverSay(std::string("example: !unban 3"), uid); - } else { + } + else + { if (UnBan(buid)) serverSay(std::string("ban removed"), uid); else serverSay(std::string("ban not removed: error"), uid); } - } else { + } + else + { // not allowed serverSay(std::string("You are not authorized to unban people!"), uid); } - } else if (str.substr(0, 5) == "!ban ") { - if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) { - int buid = -1; - char banmsg_tmp[256] = ""; - int res = sscanf(str.substr(5).c_str(), "%d %s", &buid, banmsg_tmp); - std::string banMsg = std::string(banmsg_tmp); + } + else if (str.substr(0, 5) == "!ban ") + { + if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) + { + int buid = -1; + char banmsg_tmp[256] = ""; + int res = sscanf(str.substr(5).c_str(), "%d %s", &buid, banmsg_tmp); + std::string banMsg = std::string(banmsg_tmp); banMsg = trim(banMsg); - if (res != 2 || buid == -1 || !banMsg.size()) { + if (res != 2 || buid == -1 || !banMsg.size()) + { serverSay(std::string("usage: !ban "), uid); serverSay(std::string("example: !ban 3 swearing"), uid); - } else { + } + else + { bool banned = Ban(buid, uid, str.substr(6 + intlen(buid), 256).c_str()); if (!banned) serverSay(std::string("kick + ban not successful: uid not found!"), uid); } - } else { + } + else + { // not allowed serverSay(std::string("You are not authorized to ban people!"), uid); } - } else if (str.substr(0, 6) == "!kick ") { - if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) { - int kuid = -1; - char kickmsg_tmp[256] = ""; - int res = sscanf(str.substr(6).c_str(), "%d %s", &kuid, kickmsg_tmp); - std::string kickMsg = std::string(kickmsg_tmp); + } + else if (str.substr(0, 6) == "!kick ") + { + if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) + { + int kuid = -1; + char kickmsg_tmp[256] = ""; + int res = sscanf(str.substr(6).c_str(), "%d %s", &kuid, kickmsg_tmp); + std::string kickMsg = std::string(kickmsg_tmp); kickMsg = trim(kickMsg); - if (res != 2 || kuid == -1 || !kickMsg.size()) { + if (res != 2 || kuid == -1 || !kickMsg.size()) + { serverSay(std::string("usage: !kick "), uid); serverSay(std::string("example: !kick 3 bye!"), uid); - } else { + } + else + { bool kicked = Kick(kuid, uid, str.substr(7 + intlen(kuid), 256).c_str()); if (!kicked) serverSay(std::string("kick not successful: uid not found!"), uid); } - } else { + } + else + { // not allowed serverSay(std::string("You are not authorized to kick people!"), uid); } - } else if (str == "!vehiclelimit") { + } + else if (str == "!vehiclelimit") + { char sayMsg[128] = ""; sprintf(sayMsg, "The vehicle-limit on this server is set on %d", Config::getMaxVehicles()); serverSay(sayMsg, uid, FROM_SERVER); - } else if (str.substr(0, 5) == "!say ") { - if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) { - int kuid = -2; - char saymsg_tmp[256] = ""; - int res = sscanf(str.substr(5).c_str(), "%d %s", &kuid, saymsg_tmp); - std::string sayMsg = std::string(saymsg_tmp); + } + else if (str.substr(0, 5) == "!say ") + { + if (client->user.authstatus & RoRnet::AUTH_MOD || client->user.authstatus & RoRnet::AUTH_ADMIN) + { + int kuid = -2; + char saymsg_tmp[256] = ""; + int res = sscanf(str.substr(5).c_str(), "%d %s", &kuid, saymsg_tmp); + std::string sayMsg = std::string(saymsg_tmp); sayMsg = trim(sayMsg); - if (res != 2 || kuid < -1 || !sayMsg.size()) { + if (res != 2 || kuid < -1 || !sayMsg.size()) + { serverSay(std::string("usage: !say (use uid -1 for general broadcast)"), uid); serverSay(std::string("example: !say 3 Wecome to this server!"), uid); - } else { + } + else + { serverSay(str.substr(6 + intlen(kuid), 256), kuid, FROM_HOST); } - - } else { + } + else + { // not allowed serverSay(std::string("You are not authorized to use this command!"), uid); } - } else if (str == "!website" || str == "!www") { - if (!Config::getWebsite().empty()) { + } + else if (str == "!website" || str == "!www") + { + if (!Config::getWebsite().empty()) + { char sayMsg[256] = ""; sprintf(sayMsg, "Further information can be found online at %s", Config::getWebsite().c_str()); serverSay(sayMsg, uid, FROM_SERVER); } - } else if (str == "!irc") { - if (!Config::getIRC().empty()) { + } + else if (str == "!irc") + { + if (!Config::getIRC().empty()) + { char sayMsg[256] = ""; sprintf(sayMsg, "IRC: %s", Config::getIRC().c_str()); serverSay(sayMsg, uid, FROM_SERVER); } - } else if (str == "!owner") { - if (!Config::getOwner().empty()) { + } + else if (str == "!owner") + { + if (!Config::getOwner().empty()) + { char sayMsg[256] = ""; sprintf(sayMsg, "This server is run by %s", Config::getOwner().c_str()); serverSay(sayMsg, uid, FROM_SERVER); } - } else if (str == "!voip") { - if (!Config::getVoIP().empty()) { + } + else if (str == "!voip") + { + if (!Config::getVoIP().empty()) + { char sayMsg[256] = ""; sprintf(sayMsg, "This server's official VoIP: %s", Config::getVoIP().c_str()); serverSay(sayMsg, uid, FROM_SERVER); } - } else if (str == "!rules") { - if (!Config::getRulesFile().empty()) { + } + else if (str == "!rules") + { + if (!Config::getRulesFile().empty()) + { std::vector lines; - int res = Utils::ReadLinesFromFile(Config::getRulesFile(), lines); - if (!res) { + int res = Utils::ReadLinesFromFile(Config::getRulesFile(), lines); + if (!res) + { std::vector::iterator it; - for (it = lines.begin(); it != lines.end(); it++) { + for (it = lines.begin(); it != lines.end(); it++) + { serverSay(*it, uid, FROM_RULES); } } } - } else if (str == "!motd") { + } + else if (str == "!motd") + { this->sendMOTD(uid); } - } else if (type == RoRnet::MSG2_UTF8_PRIVCHAT) { + } + else if (type == RoRnet::MSG2_UTF8_PRIVCHAT) + { // private chat message Client *dest_client = this->FindClientById(static_cast(uid)); - if (dest_client != nullptr) { + if (dest_client != nullptr) + { char *chatmsg = data + sizeof(int); - int chatlen = len - sizeof(int); + int chatlen = len - sizeof(int); dest_client->QueueMessage(RoRnet::MSG2_UTF8_PRIVCHAT, uid, streamid, chatlen, chatmsg); publishMode = BROADCAST_BLOCK; } - } else if (type == RoRnet::MSG2_GAME_CMD) { + } + else if (type == RoRnet::MSG2_GAME_CMD) + { // script message #ifdef WITH_ANGELSCRIPT - if (m_script_engine) m_script_engine->gameCmd(client->user.uniqueid, std::string(data)); -#endif //WITH_ANGELSCRIPT + if (m_script_engine) + m_script_engine->gameCmd(client->user.uniqueid, std::string(data)); +#endif //WITH_ANGELSCRIPT publishMode = BROADCAST_BLOCK; } #if 0 // replaced with stream_data - else if (type==RoRnet::MSG2_VEHICLE_DATA) + else if (type == RoRnet::MSG2_VEHICLE_DATA) { #ifdef WITH_ANGELSCRIPT - float* fpt=(float*)(data+sizeof(RoRnet::TruckState)); - client->position=Vector3(fpt[0], fpt[1], fpt[2]); -#endif //WITH_ANGELSCRIPT + float* fpt = (float*)(data + sizeof(RoRnet::TruckState)); + client->position = Vector3(fpt[0], fpt[1], fpt[2]); +#endif //WITH_ANGELSCRIPT /* - char hex[255]=""; - SHA1FromBuffer(hex, data, len); - printf("R > %s\n", hex); - - std::string hexc = hexdump(data, len); - printf("RH> %s\n", hexc.c_str()); - */ + * char hex[255]=""; + * SHA1FromBuffer(hex, data, len); + * printf("R > %s\n", hex); + * + * std::string hexc = hexdump(data, len); + * printf("RH> %s\n", hexc.c_str()); + */ - publishMode=BROADCAST_NORMAL; + publishMode = BROADCAST_NORMAL; } #endif //0 #if 0 - else if (type==RoRnet::MSG2_FORCE) + else if (type == RoRnet::MSG2_FORCE) { //this message is to be sent to only one destination - unsigned int destuid=((netforce_t*)data)->target_uid; - for ( unsigned int i = 0; i < m_clients.size(); i++) + unsigned int destuid = ((netforce_t*)data)->target_uid; + for (unsigned int i = 0; i < m_clients.size(); i++) { - if(i >= m_clients.size()) + if (i >= m_clients.size()) break; if (m_clients[i]->status == USED && m_clients[i]->flow && - m_clients[i]->user.uniqueid==destuid) + m_clients[i]->user.uniqueid == destuid) m_clients[i]->queueMessage( - client->user.uniqueid, type, len, data); + client->user.uniqueid, type, len, data); } - publishMode=BROADCAST_BLOCK; + publishMode = BROADCAST_BLOCK; } #endif //0 - if (publishMode < BROADCAST_BLOCK) { + if (publishMode < BROADCAST_BLOCK) + { client->streams_traffic[streamid].bandwidthIncoming += len; - if (publishMode == BROADCAST_NORMAL || publishMode == BROADCAST_ALL) { + if (publishMode == BROADCAST_NORMAL || publishMode == BROADCAST_ALL) + { bool toAll = (publishMode == BROADCAST_ALL); // just push to all the present clients - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { Client *curr_client = m_clients[i]; if (curr_client->GetStatus() == Client::STATUS_USED && curr_client->IsReceivingData() && - (curr_client != client || toAll)) { + (curr_client != client || toAll)) + { curr_client->streams_traffic[streamid].bandwidthOutgoing += len; curr_client->QueueMessage(type, client->user.uniqueid, streamid, len, data); } } - } else if (publishMode == BROADCAST_AUTHED) { + } + else if (publishMode == BROADCAST_AUTHED) + { // push to all bots and authed users above auth level 1 - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { Client *curr_client = m_clients[i]; if (curr_client->GetStatus() == Client::STATUS_USED && curr_client->IsReceivingData() && - (curr_client != client) && (client->user.authstatus & RoRnet::AUTH_ADMIN)) { + (curr_client != client) && (client->user.authstatus & RoRnet::AUTH_ADMIN)) + { curr_client->streams_traffic[streamid].bandwidthOutgoing += len; curr_client->QueueMessage(type, client->user.uniqueid, streamid, len, data); } @@ -1125,51 +1315,62 @@ void Sequencer::queueMessage(int uid, int type, unsigned int streamid, char *dat } } -int Sequencer::getStartTime() { +int Sequencer::getStartTime() +{ return m_start_time; } -Client *Sequencer::getClient(int uid) { +Client *Sequencer::getClient(int uid) +{ return this->FindClientById(static_cast(uid)); } -void Sequencer::UpdateMinuteStats() { +void Sequencer::UpdateMinuteStats() +{ MutexLocker scoped_lock(m_clients_mutex); - for (unsigned int i = 0; i < m_clients.size(); i++) { - if (m_clients[i]->GetStatus() == Client::STATUS_USED) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { + if (m_clients[i]->GetStatus() == Client::STATUS_USED) for (std::map::iterator it = m_clients[i]->streams_traffic.begin(); - it != m_clients[i]->streams_traffic.end(); it++) { + it != m_clients[i]->streams_traffic.end(); it++) + { it->second.bandwidthIncomingRate = - (it->second.bandwidthIncoming - it->second.bandwidthIncomingLastMinute) / 60; + (it->second.bandwidthIncoming - it->second.bandwidthIncomingLastMinute) / 60; it->second.bandwidthIncomingLastMinute = it->second.bandwidthIncoming; - it->second.bandwidthOutgoingRate = - (it->second.bandwidthOutgoing - it->second.bandwidthOutgoingLastMinute) / 60; + it->second.bandwidthOutgoingRate = + (it->second.bandwidthOutgoing - it->second.bandwidthOutgoingLastMinute) / 60; it->second.bandwidthOutgoingLastMinute = it->second.bandwidthOutgoing; } - } } } // clients_mutex needs to be locked wen calling this method -void Sequencer::printStats() { - if (!Config::getPrintStats()) { +void Sequencer::printStats() +{ + if (!Config::getPrintStats()) return; - } + { Logger::Log(LOG_INFO, "Server occupancy:"); Logger::Log(LOG_INFO, "Slot Status UID IP Colour, Nickname"); Logger::Log(LOG_INFO, "--------------------------------------------------"); - for (unsigned int i = 0; i < m_clients.size(); i++) { + for (unsigned int i = 0; i < m_clients.size(); i++) + { // some auth identifiers char authst[10] = ""; - if (m_clients[i]->user.authstatus & RoRnet::AUTH_ADMIN) strcat(authst, "A"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_MOD) strcat(authst, "M"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_RANKED) strcat(authst, "R"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_BOT) strcat(authst, "B"); - if (m_clients[i]->user.authstatus & RoRnet::AUTH_BANNED) strcat(authst, "X"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_ADMIN) + strcat(authst, "A"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_MOD) + strcat(authst, "M"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_RANKED) + strcat(authst, "R"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_BOT) + strcat(authst, "B"); + if (m_clients[i]->user.authstatus & RoRnet::AUTH_BANNED) + strcat(authst, "X"); // construct screen if (m_clients[i]->GetStatus() == Client::STATUS_USED) @@ -1189,40 +1390,44 @@ void Sequencer::printStats() { Str::SanitizeUtf8(m_clients[i]->user.username).c_str()); } Logger::Log(LOG_INFO, "--------------------------------------------------"); - int timediff = Messaging::getTime() - m_start_time; - int uphours = timediff / 60 / 60; - int upminutes = (timediff - (uphours * 60 * 60)) / 60; - stream_traffic_t traffic = Messaging::GetTrafficStats(); + int timediff = Messaging::getTime() - m_start_time; + int uphours = timediff / 60 / 60; + int upminutes = (timediff - (uphours * 60 * 60)) / 60; + stream_traffic_t traffic = Messaging::GetTrafficStats(); Logger::Log(LOG_INFO, "- traffic statistics (uptime: %d hours, %d " - "minutes):", uphours, upminutes); + "minutes):", uphours, upminutes); Logger::Log(LOG_INFO, "- total: incoming: %0.2fMB , outgoing: %0.2fMB", traffic.bandwidthIncoming / 1024 / 1024, traffic.bandwidthOutgoing / 1024 / 1024); Logger::Log(LOG_INFO, "- rate (last minute): incoming: %0.1fkB/s , " - "outgoing: %0.1fkB/s", + "outgoing: %0.1fkB/s", traffic.bandwidthIncomingRate / 1024, traffic.bandwidthOutgoingRate / 1024); } } -Client *Sequencer::FindClientById(unsigned int client_id) { +Client *Sequencer::FindClientById(unsigned int client_id) +{ auto itor = m_clients.begin(); auto endi = m_clients.end(); - for (; itor != endi; ++itor) { + + for (; itor != endi; ++itor) + { Client *client = *itor; - if (client->user.uniqueid == client_id) { + if (client->user.uniqueid == client_id) return client; - } } return nullptr; } -std::vector Sequencer::GetClientListCopy() { - MutexLocker scoped_lock(m_clients_mutex); +std::vector Sequencer::GetClientListCopy() +{ + MutexLocker scoped_lock(m_clients_mutex); std::vector output; - for (Client *c : m_clients) { + for (Client *c : m_clients) + { output.push_back(*c); } return output; diff --git a/source/server/sequencer.h b/source/server/sequencer.h index 91fe6beb..37632d5d 100644 --- a/source/server/sequencer.h +++ b/source/server/sequencer.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -43,33 +43,36 @@ along with Foobar. If not, see . // How many not-vehicles streams has every user by default? (e.g.: "default" and "chat" are not-vehicles streams) // This is used for the vehicle-limit -#define NON_VEHICLE_STREAMS 2 +#define NON_VEHICLE_STREAMS 2 -#define SEQUENCER Sequencer::Instance() +#define SEQUENCER Sequencer::Instance() -#define VERSION "$Rev$" +#define VERSION "$Rev$" // This is used to define who says it, when the server says something -enum serverSayType { +enum serverSayType +{ FROM_SERVER = 0, FROM_HOST, FROM_MOTD, FROM_RULES }; -enum broadcastType { -// order: least restrictive to most restrictive! - BROADCAST_AUTO = -1, // Do not edit the publishmode (for scripts only) - BROADCAST_ALL, // broadcast to all clients including sender - BROADCAST_NORMAL, // broadcast to all clients except sender - BROADCAST_AUTHED, // broadcast to authed users (bots) - BROADCAST_BLOCK // no broadcast +enum broadcastType +{ + // order: least restrictive to most restrictive! + BROADCAST_AUTO = -1, // Do not edit the publishmode (for scripts only) + BROADCAST_ALL, // broadcast to all clients including sender + BROADCAST_NORMAL, // broadcast to all clients except sender + BROADCAST_AUTHED, // broadcast to authed users (bots) + BROADCAST_BLOCK // no broadcast }; // constant for functions that receive an uid for sending something static const int TO_ALL = -1; -struct stream_traffic_t { +struct stream_traffic_t +{ // normal bandwidth double bandwidthIncoming; double bandwidthOutgoing; @@ -87,9 +90,11 @@ struct stream_traffic_t { double bandwidthDropOutgoingRate; }; -class Client { +class Client +{ public: - enum Status { + enum Status + { STATUS_FREE = 0, STATUS_BUSY = 1, STATUS_USED = 2 @@ -108,44 +113,61 @@ class Client { std::string GetIpAddress(); - SWInetSocket *GetSocket() { return m_socket; } + SWInetSocket *GetSocket() + { + return m_socket; + } - bool IsBroadcasterDroppingPackets() const { return m_broadcaster.IsDroppingPackets(); } + bool IsBroadcasterDroppingPackets() const + { + return m_broadcaster.IsDroppingPackets(); + } - void SetReceiveData(bool val) { m_is_receiving_data = val; } + void SetReceiveData(bool val) + { + m_is_receiving_data = val; + } - bool IsReceivingData() const { return m_is_receiving_data; } + bool IsReceivingData() const + { + return m_is_receiving_data; + } - Status GetStatus() const { return m_status; } + Status GetStatus() const + { + return m_status; + } - RoRnet::UserInfo user; //!< user information + RoRnet::UserInfo user; //!< user information - int drop_state; // dropping outgoing packets? + int drop_state; // dropping outgoing packets? //things for the communication with the webserver below, not used in the main server code std::map streams; - std::map streams_traffic; + std::map streams_traffic; private: SWInetSocket *m_socket; - Receiver m_receiver; - Broadcaster m_broadcaster; - Status m_status; - bool m_is_receiving_data; - bool m_is_initialized; + Receiver m_receiver; + Broadcaster m_broadcaster; + Status m_status; + bool m_is_receiving_data; + bool m_is_initialized; }; -struct ban_t { - unsigned int uid; //!< userid - char ip[40]; //!< ip of banned client - char nickname[RORNET_MAX_USERNAME_LEN]; //!< Username, this is what they are called to - char bannedby_nick[RORNET_MAX_USERNAME_LEN]; //!< Username, this is what they are called to - char banmsg[256]; //!< why he got banned +struct ban_t +{ + unsigned int uid; //!< userid + char ip[40]; //!< ip of banned client + char nickname[RORNET_MAX_USERNAME_LEN]; //!< Username, this is what they are called to + char bannedby_nick[RORNET_MAX_USERNAME_LEN]; //!< Username, this is what they are called to + char banmsg[256]; //!< why he got banned }; void *LaunchKillerThread(void *); -class Sequencer { +class Sequencer +{ friend void *LaunchKillerThread(void *); public: @@ -176,7 +198,7 @@ class Sequencer { UserAuth *getUserAuth(); - int getNumClients(); //! number of clients connected to this server + int getNumClients(); //! number of clients connected to this server Client *getClient(int uid); void GetHeartbeatUserList(Json::Value *out_array); @@ -219,20 +241,20 @@ class Sequencer { static unsigned int connCrash, connCount; private: - pthread_t m_killer_thread; //!< thread to handle the killing of clients - Condition m_killer_cond; //!< wait condition that there are clients to kill - Mutex m_killer_mutex; //!< mutex used for locking access to the killqueue - Mutex m_clients_mutex; //!< mutex used for locking access to the clients array - Listener *m_listener; - ScriptEngine *m_script_engine; - UserAuth *m_auth_resolver; - int m_bot_count; //!< Amount of registered bots on the server. - unsigned int m_free_user_id; - int m_start_time; - - std::queue m_kill_queue; //!< holds pointer for client deletion + pthread_t m_killer_thread; //!< thread to handle the killing of clients + Condition m_killer_cond; //!< wait condition that there are clients to kill + Mutex m_killer_mutex; //!< mutex used for locking access to the killqueue + Mutex m_clients_mutex; //!< mutex used for locking access to the clients array + Listener *m_listener; + ScriptEngine *m_script_engine; + UserAuth *m_auth_resolver; + int m_bot_count; //!< Amount of registered bots on the server. + unsigned int m_free_user_id; + int m_start_time; + + std::queue m_kill_queue; //!< holds pointer for client deletion std::vector m_clients; - std::vector m_bans; + std::vector m_bans; Client *FindClientById(unsigned int client_id); }; diff --git a/source/server/sha1.h b/source/server/sha1.h index dbcc6038..eaf0deab 100644 --- a/source/server/sha1.h +++ b/source/server/sha1.h @@ -8,15 +8,16 @@ /** * \brief SHA-1 context structure */ -typedef struct { - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ } - sha1_context; +sha1_context; #ifdef __cplusplus extern "C" { @@ -44,7 +45,7 @@ void sha1_update(sha1_context *ctx, unsigned char *input, int ilen); * \param ctx SHA-1 context * \param output SHA-1 checksum result */ -void sha1_finish(sha1_context *ctx, unsigned char output[20]); +void sha1_finish(sha1_context * ctx, unsigned char output[20]); /** * \brief Output = SHA-1( input buffer ) @@ -90,7 +91,7 @@ void sha1_hmac_update(sha1_context *ctx, unsigned char *input, int ilen); * \param ctx HMAC context * \param output SHA-1 HMAC checksum result */ -void sha1_hmac_finish(sha1_context *ctx, unsigned char output[20]); +void sha1_hmac_finish(sha1_context * ctx, unsigned char output[20]); /** * \brief Output = HMAC-SHA-1( hmac key, input buffer ) diff --git a/source/server/sha1_util.cpp b/source/server/sha1_util.cpp index 29ca8d7a..c7c0c8ab 100644 --- a/source/server/sha1_util.cpp +++ b/source/server/sha1_util.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "sha1_util.h" @@ -35,12 +35,15 @@ along with Foobar. If not, see . #include -bool toHex(char *result, unsigned char *data, unsigned int len) { - char tmp[20]; +bool toHex(char *result, unsigned char *data, unsigned int len) +{ + char tmp[20]; unsigned int i = 0; - while (i < len) { + + while (i < len) + { memset(tmp, 0, 20); - unsigned char d = (unsigned char) *data; + unsigned char d = (unsigned char)*data; sprintf(tmp, "%02X", d); strcat(result, tmp); data++; @@ -49,77 +52,90 @@ bool toHex(char *result, unsigned char *data, unsigned int len) { return true; } -bool SHA1FromString(char *result, const char *source) { +bool SHA1FromString(char *result, const char *source) +{ // init variables char sha1result_bin[20]; + memset(sha1result_bin, 0, 20); char sha1result_hex[41]; memset(sha1result_hex, 0, 41); // calculate hash of the filenames - sha1((unsigned char *) source, (int) strlen(source), (unsigned char *) sha1result_bin); - bool res = toHex(sha1result_hex, (unsigned char *) sha1result_bin, 20); + sha1((unsigned char*)source, (int)strlen(source), (unsigned char*)sha1result_bin); + bool res = toHex(sha1result_hex, (unsigned char*)sha1result_bin, 20); memcpy(result, sha1result_hex, 40); result[40] = 0; return res; } -bool SHA1FromBuffer(char *result, const char *source, int len) { +bool SHA1FromBuffer(char *result, const char *source, int len) +{ // init variables char sha1result_bin[20]; + memset(sha1result_bin, 0, 20); char sha1result_hex[2048]; memset(sha1result_hex, 0, 2048); // calculate hash of the filenames - sha1((unsigned char *) source, len, (unsigned char *) sha1result_bin); - bool res = toHex(sha1result_hex, (unsigned char *) sha1result_bin, 20); + sha1((unsigned char*)source, len, (unsigned char*)sha1result_bin); + bool res = toHex(sha1result_hex, (unsigned char*)sha1result_bin, 20); memcpy(result, sha1result_hex, 40); result[40] = 0; return res; } -bool SHA1FromString(std::string &result, const std::string &sourceStr) { +bool SHA1FromString(std::string &result, const std::string &sourceStr) +{ // init variables char sha1result_bin[20]; + memset(sha1result_bin, 0, 20); char sha1result_hex[41]; memset(sha1result_hex, 0, 41); // calculate hash of the filenames char *source = const_cast(sourceStr.c_str()); - sha1((unsigned char *) source, (int) strlen(source), (unsigned char *) sha1result_bin); - bool res = toHex(sha1result_hex, (unsigned char *) sha1result_bin, 20); - if (res) { + sha1((unsigned char*)source, (int)strlen(source), (unsigned char*)sha1result_bin); + bool res = toHex(sha1result_hex, (unsigned char*)sha1result_bin, 20); + if (res) + { sha1result_hex[40] = 0; - result = std::string(sha1result_hex); + result = std::string(sha1result_hex); } return res; } -int getFileHash(char *filename, char *hash) { +int getFileHash(char *filename, char *hash) +{ FILE *cfd = fopen(filename, "rb"); + // anti-hacker :| - if (cfd) { + if (cfd) + { // obtain file size: fseek(cfd, 0, SEEK_END); unsigned long lSize = ftell(cfd); - if (lSize <= 0) { + if (lSize <= 0) + { fclose(cfd); return 1; } rewind(cfd); // allocate memory to contain the whole file: - char *buffer = (char *) malloc(sizeof(char) * (lSize + 1)); - if (buffer == NULL) { + char *buffer = (char*)malloc(sizeof(char) * (lSize + 1)); + if (buffer == NULL) + { fclose(cfd); return -3; } memset(buffer, 0, lSize); // copy the file into the buffer: size_t result = fread(buffer, 1, lSize, cfd); - if (result != lSize) { + if (result != lSize) + { free(buffer); fclose(cfd); return -2; @@ -131,12 +147,14 @@ int getFileHash(char *filename, char *hash) { char sha1result[250]; memset(sha1result, 0, 250); - if (lSize < 300) { + if (lSize < 300) + { free(buffer); return -4; } - if (!SHA1FromString(sha1result, buffer)) { + if (!SHA1FromString(sha1result, buffer)) + { free(buffer); return -1; } @@ -149,10 +167,12 @@ int getFileHash(char *filename, char *hash) { return 1; } -bool sha1check() { - char testStr[255] = "The quick brown fox jumps over the lazy dog"; - char result[255] = ""; +bool sha1check() +{ + char testStr[255] = "The quick brown fox jumps over the lazy dog"; + char result[255] = ""; char testvalue[255] = "2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12"; + SHA1FromString(result, testStr); return !strcmp(result, testvalue); } diff --git a/source/server/sha1config.h b/source/server/sha1config.h index b284a46a..1a83384d 100644 --- a/source/server/sha1config.h +++ b/source/server/sha1config.h @@ -10,31 +10,31 @@ #define XYSSL_CONFIG_H #ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 #endif /* * Uncomment if native integers are 8-bit wide. * -#define XYSSL_HAVE_INT8 + ********#define XYSSL_HAVE_INT8 */ /* * Uncomment if native integers are 16-bit wide. * -#define XYSSL_HAVE_INT16 + ********#define XYSSL_HAVE_INT16 */ /* * Uncomment if the compiler supports long long. * -#define XYSSL_HAVE_LONGLONG + ********#define XYSSL_HAVE_LONGLONG */ /* * Uncomment if the CPU supports SSE2 (IA-32 specific). * -#define XYSSL_HAVE_SSE2 + ********#define XYSSL_HAVE_SSE2 */ /* @@ -55,7 +55,7 @@ /* * Uncomment this macro to store the AES tables in ROM. * -#define XYSSL_AES_ROM_TABLES + ********#define XYSSL_AES_ROM_TABLES */ /* diff --git a/source/server/userauth.cpp b/source/server/userauth.cpp index 6bf16f54..e0f0acda 100644 --- a/source/server/userauth.cpp +++ b/source/server/userauth.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "userauth.h" @@ -38,25 +38,31 @@ along with Foobar. If not, see . #endif -UserAuth::UserAuth(std::string _challenge, int _trustlevel, std::string authFile) { - challenge = _challenge; +UserAuth::UserAuth(std::string _challenge, int _trustlevel, std::string authFile) +{ + challenge = _challenge; trustlevel = _trustlevel; readConfig(authFile.c_str()); } -UserAuth::~UserAuth(void) { +UserAuth::~UserAuth(void) +{ } -int UserAuth::readConfig(const char *authFile) { +int UserAuth::readConfig(const char *authFile) +{ FILE *f = fopen(authFile, "r"); - if (!f) { + + if (!f) + { Logger::Log(LOG_WARN, "Couldn't open the local authorizations file ('%s'). No authorizations were loaded.", authFile); return -1; } Logger::Log(LOG_VERBOSE, "Reading the local authorizations file..."); int linecounter = 0; - while (!feof(f)) { + while (!feof(f)) + { char line[2048] = ""; memset(line, 0, 2048); fgets(line, 2048, f); @@ -72,30 +78,35 @@ int UserAuth::readConfig(const char *authFile) { // this is setup mode (server) // strip line (newline char) char *ptr = line; - while (*ptr) { - if (*ptr == '\n') { + while (*ptr) + { + if (*ptr == '\n') + { *ptr = 0; break; } ptr++; } - int authmode = RoRnet::AUTH_NONE; + int authmode = RoRnet::AUTH_NONE; char token[256]; char user_nick[40] = ""; - int res = sscanf(line, "%d %s %s", &authmode, token, user_nick); - if (res != 3 && res != 2) { + int res = sscanf(line, "%d %s %s", &authmode, token, user_nick); + if (res != 3 && res != 2) + { Logger::Log(LOG_ERROR, "error parsing authorizations file: " + std::string(line)); continue; } // Not every auth mode is allowed to be set using the configuration file - if (authmode & RoRnet::AUTH_RANKED) authmode &= ~RoRnet::AUTH_RANKED; - if (authmode & RoRnet::AUTH_BANNED) authmode &= ~RoRnet::AUTH_BANNED; + if (authmode & RoRnet::AUTH_RANKED) + authmode &= ~RoRnet::AUTH_RANKED; + if (authmode & RoRnet::AUTH_BANNED) + authmode &= ~RoRnet::AUTH_BANNED; Logger::Log(LOG_DEBUG, "adding entry to local auth cache, size: %d", local_auth.size()); user_auth_pair_t p; - p.first = authmode; - p.second = Str::SanitizeUtf8(user_nick); + p.first = authmode; + p.second = Str::SanitizeUtf8(user_nick); local_auth[std::string(token)] = p; } Logger::Log(LOG_INFO, "found %d auth overrides in the authorizations file!", local_auth.size()); @@ -103,65 +114,75 @@ int UserAuth::readConfig(const char *authFile) { return 0; } -int UserAuth::getAuthSize() { +int UserAuth::getAuthSize() +{ return local_auth.size(); } -void UserAuth::clearCache() { +void UserAuth::clearCache() +{ local_auth.clear(); } -std::map UserAuth::getAuthCache() { +std::map UserAuth::getAuthCache() +{ return cache; } -int UserAuth::setUserAuth(int flags, std::string user_nick, std::string token) { +int UserAuth::setUserAuth(int flags, std::string user_nick, std::string token) +{ user_auth_pair_t p; - p.first = flags; - p.second = user_nick; + + p.first = flags; + p.second = user_nick; local_auth[token] = p; return 0; } -int UserAuth::sendUserEvent(std::string user_token, std::string type, std::string arg1, std::string arg2) { +int UserAuth::sendUserEvent(std::string user_token, std::string type, std::string arg1, std::string arg2) +{ /* #### DISABLED UNTIL SUPPORTED BY NEW MULTIPLAYER PORTAL #### - - // Only contact the master server if we are allowed to do so - if(trustlevel<=1) return 0; - - char url[2048]; - sprintf(url, "%s/userevent_utf8/?v=0&sh=%s&h=%s&t=%s&a1=%s&a2=%s", REPO_URLPREFIX, challenge.c_str(), user_token.c_str(), type.c_str(), arg1.c_str(), arg2.c_str()); - Logger::Log(LOG_DEBUG, "UserAuth event to server: " + std::string(url)); - Http::Response resp; - if (HTTPGET(url, resp) < 0) - { - Logger::Log(LOG_ERROR, "UserAuth event query result empty"); - return -1; - } - - std::string body = resp.GetBody(); - Logger::Log(LOG_DEBUG,"UserEvent reply: " + body); - - return (body!="ok"); - - */ + * + * // Only contact the master server if we are allowed to do so + * if(trustlevel<=1) return 0; + * + * char url[2048]; + * sprintf(url, "%s/userevent_utf8/?v=0&sh=%s&h=%s&t=%s&a1=%s&a2=%s", REPO_URLPREFIX, challenge.c_str(), user_token.c_str(), type.c_str(), arg1.c_str(), arg2.c_str()); + * Logger::Log(LOG_DEBUG, "UserAuth event to server: " + std::string(url)); + * Http::Response resp; + * if (HTTPGET(url, resp) < 0) + * { + * Logger::Log(LOG_ERROR, "UserAuth event query result empty"); + * return -1; + * } + * + * std::string body = resp.GetBody(); + * Logger::Log(LOG_DEBUG,"UserEvent reply: " + body); + * + * return (body!="ok"); + * + */ return -1; } -std::string UserAuth::getNewPlayernameByID(int id) { +std::string UserAuth::getNewPlayernameByID(int id) +{ char tmp[255] = ""; + sprintf(tmp, "Player%d", id); return std::string(tmp); } -int UserAuth::resolve(std::string user_token, std::string &user_nick, int clientid) { +int UserAuth::resolve(std::string user_token, std::string &user_nick, int clientid) +{ // There's alot of other info in the user token variable, but we don't need it here. // We only need the first 40 characters = the actual (encoded) token. user_token = user_token.substr(0, 40); //check cache first - if (cache.find(user_token) != cache.end()) { + if (cache.find(user_token) != cache.end()) + { // cache hit! user_nick = cache[user_token].second; return cache[user_token].first; @@ -171,66 +192,68 @@ int UserAuth::resolve(std::string user_token, std::string &user_nick, int client int authlevel = RoRnet::AUTH_NONE; // Only contact the master-server if we're allowed to do so - if (trustlevel > 1) { + if (trustlevel > 1) + { // not found in cache or local_auth, get auth from masterserver /* #### DISABLED UNTIL SUPPORTED BY NEW MULTIPLAYER PORTAL #### - - std::string msg = ""; - UTFString resultNick = L""; - - char url[2048]; - sprintf(url, "%s/authuser_utf8/?c=%s&t=%s&u=%s", REPO_URLPREFIX, challenge.c_str(), user_token.c_str(), user_nick.asUTF8_c_str()); - Logger::Log(LOG_DEBUG, "UserAuth query to server: " + std::string(url)); - Http::Response resp; - if (HTTPGET(url, resp) < 0) - { - Logger::Log(LOG_ERROR, "UserAuth resolve query result empty"); - return RoRnet::AUTH_NONE; - } - - std::string body = resp.GetBody(); - Logger::Log(LOG_DEBUG,"UserAuth reply: " + body); - - std::vector args; - strict_tokenize(body, args, "\t"); - - if(args.size() < 2) - { - Logger::Log(LOG_INFO,"UserAuth: invalid return value from server: " + body); - return RoRnet::AUTH_NONE; - } - - authlevel = atoi(args[0].c_str()); - resultNick = tryConvertUTF(args[1].c_str()); - if(args.size() > 2) - msg = args[2]; - - // debug output the auth status - UTFString authst; - if(authlevel & RoRnet::AUTH_NONE) authst = authst + "N"; - if(authlevel & RoRnet::AUTH_ADMIN) authst = authst + "A"; - if(authlevel & RoRnet::AUTH_MOD) authst = authst + "M"; - if(authlevel & RoRnet::AUTH_RANKED) authst = authst + "R"; - if(authlevel & RoRnet::AUTH_BOT) authst = authst + "B"; - if(authst.empty()) authst = "(none)"; - Logger::Log(LOG_DEBUG, UTFString("User Auth Result: ") + authst + " / " + (resultNick) + " / " + tryConvertUTF(msg.c_str())); - - if(resultNick == L"error" || resultNick == L"reserved" || resultNick == L"notranked") - { - resultNick = widen(getNewPlayernameByID(clientid)); - Logger::Log(LOG_DEBUG, UTFString("got new random name for player: ") + resultNick); - authlevel = RoRnet::AUTH_NONE; - } - - // returned name valid, use it - user_nick = resultNick; - - */ + * + * std::string msg = ""; + * UTFString resultNick = L""; + * + * char url[2048]; + * sprintf(url, "%s/authuser_utf8/?c=%s&t=%s&u=%s", REPO_URLPREFIX, challenge.c_str(), user_token.c_str(), user_nick.asUTF8_c_str()); + * Logger::Log(LOG_DEBUG, "UserAuth query to server: " + std::string(url)); + * Http::Response resp; + * if (HTTPGET(url, resp) < 0) + * { + * Logger::Log(LOG_ERROR, "UserAuth resolve query result empty"); + * return RoRnet::AUTH_NONE; + * } + * + * std::string body = resp.GetBody(); + * Logger::Log(LOG_DEBUG,"UserAuth reply: " + body); + * + * std::vector args; + * strict_tokenize(body, args, "\t"); + * + * if(args.size() < 2) + * { + * Logger::Log(LOG_INFO,"UserAuth: invalid return value from server: " + body); + * return RoRnet::AUTH_NONE; + * } + * + * authlevel = atoi(args[0].c_str()); + * resultNick = tryConvertUTF(args[1].c_str()); + * if(args.size() > 2) + * msg = args[2]; + * + * // debug output the auth status + * UTFString authst; + * if(authlevel & RoRnet::AUTH_NONE) authst = authst + "N"; + * if(authlevel & RoRnet::AUTH_ADMIN) authst = authst + "A"; + * if(authlevel & RoRnet::AUTH_MOD) authst = authst + "M"; + * if(authlevel & RoRnet::AUTH_RANKED) authst = authst + "R"; + * if(authlevel & RoRnet::AUTH_BOT) authst = authst + "B"; + * if(authst.empty()) authst = "(none)"; + * Logger::Log(LOG_DEBUG, UTFString("User Auth Result: ") + authst + " / " + (resultNick) + " / " + tryConvertUTF(msg.c_str())); + * + * if(resultNick == L"error" || resultNick == L"reserved" || resultNick == L"notranked") + * { + * resultNick = widen(getNewPlayernameByID(clientid)); + * Logger::Log(LOG_DEBUG, UTFString("got new random name for player: ") + resultNick); + * authlevel = RoRnet::AUTH_NONE; + * } + * + * // returned name valid, use it + * user_nick = resultNick; + * + */ } //then check for overrides in the authorizations file (server admins, etc) - if (local_auth.find(user_token) != local_auth.end()) { + if (local_auth.find(user_token) != local_auth.end()) + { // local auth hit! // the stored nickname can be empty if no nickname is specified. if (!local_auth[user_token].second.empty()) @@ -239,9 +262,10 @@ int UserAuth::resolve(std::string user_token, std::string &user_nick, int client } // cache result if ranked or higher - if (authlevel > RoRnet::AUTH_NONE) { + if (authlevel > RoRnet::AUTH_NONE) + { user_auth_pair_t p; - p.first = authlevel; + p.first = authlevel; p.second = user_nick; Logger::Log(LOG_DEBUG, "adding entry to remote auth cache, size: %d", cache.size()); @@ -251,58 +275,60 @@ int UserAuth::resolve(std::string user_token, std::string &user_nick, int client return authlevel; } -int UserAuth::HTTPGET(const char *URL, Http::Response &resp) { - if (trustlevel <= 1) { +int UserAuth::HTTPGET(const char *URL, Http::Response &resp) +{ + if (trustlevel <= 1) + { // If this happens, then you did something wrong in the server code Logger::Log(LOG_ERROR, "userauth: tried to contact master server without permission. URL: %s", URL); return 0; } /* #### DISABLED UNTIL SUPPORTED BY NEW MULTIPLAYER PORTAL #### - - char httpresp[65536]; //!< http response from the master server - int res=0; - SWBaseSocket::SWBaseError error; - SWInetSocket mySocket; - - if (mySocket.connect(80, REPO_SERVER, &error)) - { - char query[2048]; - sprintf(query, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", URL, REPO_SERVER); - Logger::Log(LOG_DEBUG,"Query to Master server: %s", query); - if (mySocket.sendmsg(query, &error)<0) - { - Logger::Log(LOG_ERROR,"Notifier: could not send request (%s)", error.get_error().c_str()); - res=-1; - } - int rlen=mySocket.recv(httpresp, 65536, &error); - if (rlen>0 && rlen<65535) httpresp[rlen]=0; - else - { - Logger::Log(LOG_ERROR,"Notifier: could not get a valid response (%s)", error.get_error().c_str()); - res=-1; - } - Logger::Log(LOG_DEBUG,"Response from Master server:'%s'", httpresp); - try - { - resp.FromBuffer(std::string(httpresp)); - } - catch( std::runtime_error e) - { - Logger::Log(LOG_ERROR, e.what() ); - res = -1; - } - // disconnect - mySocket.disconnect(); - } - else - { - Logger::Log(LOG_ERROR,"Notifier: could not connect to the Master server (%s)", error.get_error().c_str()); - res=-1; - } - return res; - - */ + * + * char httpresp[65536]; //!< http response from the master server + * int res=0; + * SWBaseSocket::SWBaseError error; + * SWInetSocket mySocket; + * + * if (mySocket.connect(80, REPO_SERVER, &error)) + * { + * char query[2048]; + * sprintf(query, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", URL, REPO_SERVER); + * Logger::Log(LOG_DEBUG,"Query to Master server: %s", query); + * if (mySocket.sendmsg(query, &error)<0) + * { + * Logger::Log(LOG_ERROR,"Notifier: could not send request (%s)", error.get_error().c_str()); + * res=-1; + * } + * int rlen=mySocket.recv(httpresp, 65536, &error); + * if (rlen>0 && rlen<65535) httpresp[rlen]=0; + * else + * { + * Logger::Log(LOG_ERROR,"Notifier: could not get a valid response (%s)", error.get_error().c_str()); + * res=-1; + * } + * Logger::Log(LOG_DEBUG,"Response from Master server:'%s'", httpresp); + * try + * { + * resp.FromBuffer(std::string(httpresp)); + * } + * catch( std::runtime_error e) + * { + * Logger::Log(LOG_ERROR, e.what() ); + * res = -1; + * } + * // disconnect + * mySocket.disconnect(); + * } + * else + * { + * Logger::Log(LOG_ERROR,"Notifier: could not connect to the Master server (%s)", error.get_error().c_str()); + * res=-1; + * } + * return res; + * + */ return -1; } diff --git a/source/server/userauth.h b/source/server/userauth.h index 8864e27e..60579d08 100644 --- a/source/server/userauth.h +++ b/source/server/userauth.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -25,16 +25,17 @@ along with Foobar. If not, see . #include -typedef std::pair user_auth_pair_t; +typedef std::pair user_auth_pair_t; -class UserAuth { +class UserAuth +{ private: std::map cache; int HTTPGET(const char *URL, Http::Response &resp); - std::string challenge; - int trustlevel; + std::string challenge; + int trustlevel; std::map local_auth; int readConfig(const char *authFile); diff --git a/source/server/utils.cpp b/source/server/utils.cpp index bc13d5be..214125a6 100644 --- a/source/server/utils.cpp +++ b/source/server/utils.cpp @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #include "utils.h" @@ -40,31 +40,37 @@ along with Foobar. If not, see . #endif -namespace Utils { - - int generateRandomPortNumber() { +namespace Utils +{ + int generateRandomPortNumber() + { unsigned int tick_count = 0; + // we need to be that precise here as it may happen that we start several servers at once, and thus the seed must be different #ifdef _WIN32 LARGE_INTEGER tick; QueryPerformanceCounter(&tick); tick_count = (unsigned int)tick.QuadPart; -#else // _WIN32 +#else // _WIN32 struct timeval now; gettimeofday(&now, NULL); tick_count = (now.tv_sec * 1000) + (now.tv_usec / 1000); -#endif // _WIN32 +#endif // _WIN32 // init the random number generator srand(tick_count); return 12000 + (rand() % 1000); } - int ReadLinesFromFile(std::string filename, std::vector &lines) { + int ReadLinesFromFile(std::string filename, std::vector &lines) + { FILE *f = fopen(filename.c_str(), "r"); + if (!f) return -1; + int linecounter = 0; - while (!feof(f)) { + while (!feof(f)) + { char line[2048] = ""; memset(line, 0, 2048); fgets(line, 2048, f); @@ -75,8 +81,10 @@ namespace Utils { // strip line (newline char) char *ptr = line; - while (*ptr) { - if (*ptr == '\n') { + while (*ptr) + { + if (*ptr == '\n') + { *ptr = 0; break; } @@ -88,26 +96,29 @@ namespace Utils { return 0; } - void SleepSeconds(unsigned int seconds) { + void SleepSeconds(unsigned int seconds) + { #ifndef _WIN32 sleep(seconds); #else Sleep(seconds * 1000); #endif } - } // namespace Utils using namespace std; void tokenize(const std::string &str, std::vector &tokens, - const std::string &delimiters) { + const std::string &delimiters) +{ // Skip delimiters at beginning. std::string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first "non-delimiter". std::string::size_type pos = str.find_first_of(delimiters, lastPos); - while (std::string::npos != pos || std::string::npos != lastPos) { + + while (std::string::npos != pos || std::string::npos != lastPos) + { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delimiters. Note the "not_of" @@ -123,72 +134,84 @@ void tokenize(const std::string &str, //! a single empty string. void strict_tokenize(const std::string &str, std::vector &tokens, - const std::string &delimiter) { + const std::string &delimiter) +{ size_t prev_loc = 0, new_loc = str.find(delimiter, prev_loc); - while (new_loc < str.length() && prev_loc < str.length()) { + while (new_loc < str.length() && prev_loc < str.length()) + { tokens.push_back(str.substr(prev_loc, new_loc - prev_loc)); prev_loc = (new_loc > str.length() ? new_loc : new_loc + delimiter.length()); - new_loc = str.find(delimiter, prev_loc); + new_loc = str.find(delimiter, prev_loc); } tokens.push_back(str.substr(prev_loc, new_loc - prev_loc)); } -std::string trim(const std::string &str) { - if (!str.size()) return str; +std::string trim(const std::string &str) +{ + if (!str.size()) + return str; + return str.substr(str.find_first_not_of(" \t"), str.find_last_not_of(" \t") + 1); } -std::string hexdump(void *pAddressIn, long lSize) { +std::string hexdump(void *pAddressIn, long lSize) +{ char szBuf[100]; long lIndent = 1; long lOutLen, lIndex, lIndex2, lOutLen2; long lRelPos; - struct { - char *pData; + + struct + { + char *pData; unsigned long lSize; - } buf; + } buf; unsigned char *pTmp, ucTmp; - unsigned char *pAddress = (unsigned char *) pAddressIn; + unsigned char *pAddress = (unsigned char*)pAddressIn; - buf.pData = (char *) pAddress; + buf.pData = (char*)pAddress; buf.lSize = lSize; std::string result = ""; - while (buf.lSize > 0) { - pTmp = (unsigned char *) buf.pData; - lOutLen = (int) buf.lSize; + while (buf.lSize > 0) + { + pTmp = (unsigned char*)buf.pData; + lOutLen = (int)buf.lSize; if (lOutLen > 16) lOutLen = 16; // create a 64-character formatted output line: sprintf(szBuf, " > " " " - " %08lX", (long unsigned int) (pTmp - pAddress)); + " %08lX", (long unsigned int)(pTmp - pAddress)); lOutLen2 = lOutLen; for (lIndex = 1 + lIndent, lIndex2 = 53 - 15 + lIndent, lRelPos = 0; lOutLen2; lOutLen2--, lIndex += 2, lIndex2++ - ) { + ) + { ucTmp = *pTmp++; - sprintf(szBuf + lIndex, "%02X ", (unsigned short) ucTmp); - if (!isprint(ucTmp)) ucTmp = '.'; // nonprintable char + sprintf(szBuf + lIndex, "%02X ", (unsigned short)ucTmp); + if (!isprint(ucTmp)) + ucTmp = '.'; // nonprintable char szBuf[lIndex2] = ucTmp; - if (!(++lRelPos & 3)) // extra blank after 4 bytes + if (!(++lRelPos & 3)) // extra blank after 4 bytes { lIndex++; szBuf[lIndex + 2] = ' '; } } - if (!(lRelPos & 3)) lIndex--; + if (!(lRelPos & 3)) + lIndex--; - szBuf[lIndex] = '<'; + szBuf[lIndex] = '<'; szBuf[lIndex + 1] = ' '; result += std::string(szBuf) + "\n"; @@ -200,15 +223,18 @@ std::string hexdump(void *pAddressIn, long lSize) { } // Calculates the length of an integer -int intlen(int num) { +int intlen(int num) +{ int length = 0; - if (num < 0) { - num = num * (-1); - length = 1; // set on 1 because of the minus sign + if (num < 0) + { + num = num * (-1); + length = 1; // set on 1 because of the minus sign } - while (num > 0) { + while (num > 0) + { length++; num = num / 10; } diff --git a/source/server/utils.h b/source/server/utils.h index 20ed4c27..826d1e8f 100644 --- a/source/server/utils.h +++ b/source/server/utils.h @@ -1,22 +1,22 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". If not, see . + */ #pragma once @@ -27,14 +27,13 @@ along with Foobar. If not, see . #include #include -namespace Utils { - +namespace Utils +{ int generateRandomPortNumber(); int ReadLinesFromFile(::std::string filename, std::vector &lines); void SleepSeconds(unsigned int seconds); - } // namespace Utils void tokenize(const std::string &str, @@ -51,14 +50,14 @@ void strict_tokenize(const std::string &str, template T from_string(const std::string &s, - std::ios_base &(*f)(std::ios_base &)) { - + std::ios_base & (*f)(std::ios_base &)) +{ std::istringstream iss(s); - T t; - if (!(iss >> f >> t).fail()) { + T t; + + if (!(iss >> f >> t).fail()) throw std::runtime_error(s + " is not a numerical value"); - } return t; } diff --git a/source/server/webserver.cpp b/source/server/webserver.cpp index 0b28c88e..b584f083 100644 --- a/source/server/webserver.cpp +++ b/source/server/webserver.cpp @@ -1,23 +1,23 @@ /* -This file is part of "Rigs of Rods Server" (Relay mode) - -Copyright 2007 Pierre-Michel Ricordel -Copyright 2014+ Rigs of Rods Community - -"Rigs of Rods Server" is free software: you can redistribute it -and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation, either version 3 -of the License, or (at your option) any later version. - -"Rigs of Rods Server" is distributed in the hope that it will -be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with "Rigs of Rods Server". -If not, see . -*/ + * This file is part of "Rigs of Rods Server" (Relay mode) + * + * Copyright 2007 Pierre-Michel Ricordel + * Copyright 2014+ Rigs of Rods Community + * + * "Rigs of Rods Server" is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * "Rigs of Rods Server" is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "Rigs of Rods Server". + * If not, see . + */ #ifdef WITH_WEBSERVER @@ -37,7 +37,7 @@ struct mg_context *ctx; #ifdef _WIN32 #include -#define snprintf _snprintf +#define snprintf _snprintf #ifndef _WIN32_WCE #ifdef _MSC_VER /* pragmas not valid on MinGW */ @@ -79,61 +79,65 @@ struct mg_context *ctx; #include "mongoose.h" -struct colour_t { +struct colour_t +{ double r, g, b; }; // some colours with a good contrast inbetween static colour_t s_colors[] = - { - {0.0, 0.8, 0.0}, - {0.0, 0.4, 0.701960784314}, - {1.0, 0.501960784314, 0.0}, - {1.0, 0.8, 0.0}, - {0.2, 0.0, 0.6}, - {0.6, 0.0, 0.6}, - {0.8, 1.0, 0.0}, - {1.0, 0.0, 0.0}, - {0.501960784314, 0.501960784314, 0.501960784314}, - {0.0, 0.560784313725, 0.0}, - {0.0, 0.282352941176, 0.490196078431}, - {0.701960784314, 0.352941176471, 0.0}, - {0.701960784314, 0.560784313725, 0.0}, - {0.419607843137, 0.0, 0.419607843137}, - {0.560784313725, 0.701960784314, 0.0}, - {0.701960784314, 0.0, 0.0}, - {0.745098039216, 0.745098039216, 0.745098039216}, - {0.501960784314, 1.0, 0.501960784314}, - {0.501960784314, 0.788235294118, 1.0}, - {1.0, 0.752941176471, 0.501960784314}, - {1.0, 0.901960784314, 0.501960784314}, - {0.666666666667, 0.501960784314, 1.0}, - {0.933333333333, 0.0, 0.8}, - {1.0, 0.501960784314, 0.501960784314}, - {0.4, 0.4, 0.0}, - {1.0, 0.749019607843, 1.0}, - {0.0, 1.0, 0.8}, - {0.8, 0.4, 0.6}, - {0.6, 0.6, 0.0}, - }; - -static bool s_is_advertised; -static int s_trust_level; +{ + { 0.0, 0.8, 0.0 }, + { 0.0, 0.4, 0.701960784314 }, + { 1.0, 0.501960784314, 0.0 }, + { 1.0, 0.8, 0.0 }, + { 0.2, 0.0, 0.6 }, + { 0.6, 0.0, 0.6 }, + { 0.8, 1.0, 0.0 }, + { 1.0, 0.0, 0.0 }, + { 0.501960784314, 0.501960784314, 0.501960784314 }, + { 0.0, 0.560784313725, 0.0 }, + { 0.0, 0.282352941176, 0.490196078431 }, + { 0.701960784314, 0.352941176471, 0.0 }, + { 0.701960784314, 0.560784313725, 0.0 }, + { 0.419607843137, 0.0, 0.419607843137 }, + { 0.560784313725, 0.701960784314, 0.0 }, + { 0.701960784314, 0.0, 0.0 }, + { 0.745098039216, 0.745098039216, 0.745098039216 }, + { 0.501960784314, 1.0, 0.501960784314 }, + { 0.501960784314, 0.788235294118, 1.0 }, + { 1.0, 0.752941176471, 0.501960784314 }, + { 1.0, 0.901960784314, 0.501960784314 }, + { 0.666666666667, 0.501960784314, 1.0 }, + { 0.933333333333, 0.0, 0.8 }, + { 1.0, 0.501960784314, 0.501960784314 }, + { 0.4, 0.4, 0.0 }, + { 1.0, 0.749019607843, 1.0 }, + { 0.0, 1.0, 0.8 }, + { 0.8, 0.4, 0.6 }, + { 0.6, 0.6, 0.0 }, +}; + +static bool s_is_advertised; +static int s_trust_level; static Sequencer *s_sequencer; -int getPlayerColour(int num, char *res) { +int getPlayerColour(int num, char *res) +{ int numColours = sizeof(s_colors) / sizeof(colour_t); if (num < 0 || num > numColours) return 1; - sprintf(res, "rgb(%d,%d,%d)", (int) (s_colors[num].r * 255.0f), (int) (s_colors[num].g * 255.0f), - (int) (s_colors[num].b * 255.0f)); + sprintf(res, "rgb(%d,%d,%d)", (int)(s_colors[num].r * 255.0f), (int)(s_colors[num].g * 255.0f), + (int)(s_colors[num].b * 255.0f)); return 0; } -std::string formatBytes(double bytes, bool persec = false) { +std::string formatBytes(double bytes, bool persec = false) +{ char res[256] = ""; + if (bytes < 1) sprintf(res, "0"); else if (bytes <= 1024) @@ -142,7 +146,7 @@ std::string formatBytes(double bytes, bool persec = false) { sprintf(res, "%0.2f KB", bytes / 1024.0f); else if (bytes > 1048576 && bytes <= 1073741824) sprintf(res, "%0.2f MB", bytes / 1024.0f / 1024.0f); - else //if(bytes > 1073741824 && bytes <= 1099511627776) + else //if(bytes > 1073741824 && bytes <= 1099511627776) sprintf(res, "%0.2f GB", bytes / 1024.0f / 1024.0f / 1024.0f); //else if(bytes > 1099511627776) // sprintf(res, "%0.2f TB", bytes / 1024.0f / 1024.0f / 1024.0f / 1024.0f); @@ -151,12 +155,15 @@ std::string formatBytes(double bytes, bool persec = false) { return std::string(res); } -static void renderJSONHeader(struct mg_connection *conn) { +static void renderJSONHeader(struct mg_connection *conn) +{ std::string json_header = "HTTP/1.1 200 OK\r\nCache-Control: no-cache, must-revalidate\r\nExpires: Mon, 26 Jul 1997 05:00:00 GMT\r\nContent-type: application/json\r\n\r\n"; + mg_write(conn, json_header.c_str(), json_header.size()); } -static ctemplate::TemplateDictionary *getTemplateDict(std::string title) { +static ctemplate::TemplateDictionary *getTemplateDict(std::string title) +{ ctemplate::TemplateDictionary *dict = new ctemplate::TemplateDictionary("website"); // if you remove the following line, it will enforce reading from the disc -> nice to create the templates @@ -171,8 +178,10 @@ static ctemplate::TemplateDictionary *getTemplateDict(std::string title) { return dict; } -static void renderTemplate(ctemplate::TemplateDictionary *dict, struct mg_connection *conn, std::string templatefile) { +static void renderTemplate(ctemplate::TemplateDictionary *dict, struct mg_connection *conn, std::string templatefile) +{ std::string output; + ctemplate::ExpandTemplate(templatefile, ctemplate::DO_NOT_STRIP, dict, &output); mg_write(conn, output.c_str(), output.size()); @@ -181,7 +190,8 @@ static void renderTemplate(ctemplate::TemplateDictionary *dict, struct mg_connec dict = 0; } -static void show_index(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) { +static void show_index(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) +{ ctemplate::TemplateDictionary *dict = getTemplateDict("Overview"); dict->SetValue("FOO", "test123"); @@ -189,42 +199,51 @@ static void show_index(struct mg_connection *conn, const struct mg_request_info renderTemplate(dict, conn, Config::getResourceDir() + "webserver/templates/overview.html"); } -#define ranrange(a, b) (int)((a) + rand()/(RAND_MAX + 1.0) * ((b) - (a) + 1)) +#define ranrange(a, b) (int)((a) + rand() / (RAND_MAX + 1.0) * ((b) - (a) + 1)) -static void data_stats_traffic(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) { - Json::Value root; // will contains the root value after parsing. +static void data_stats_traffic(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) +{ + Json::Value root; // will contains the root value after parsing. Json::Value results; - for (int i = 0; i < 10; i++) { - double val = ranrange(0, 100); + + for (int i = 0; i < 10; i++) + { + double val = ranrange(0, 100); Json::Value result; - result["Name"] = i; - result["Value"] = (int) val; + result["Name"] = i; + result["Value"] = (int)val; results.append(result); } root["Traffic"] = results; Json::FastWriter writer; - std::string output = writer.write(root); + std::string output = writer.write(root); renderJSONHeader(conn); mg_write(conn, output.c_str(), output.size()); } -static Json::Value ConfToJson(std::string name, std::string value) { +static Json::Value ConfToJson(std::string name, std::string value) +{ Json::Value result; - result["name"] = name; + + result["name"] = name; result["value"] = value; return result; } -static Json::Value ConfToJson(std::string name, int value) { +static Json::Value ConfToJson(std::string name, int value) +{ Json::Value result; - result["name"] = name; + + result["name"] = name; result["value"] = value; return result; } -static void data_configuration(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) { +static void data_configuration(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) +{ Json::Value results; + results.append(ConfToJson("Max Clients", Config::getMaxClients())); results.append(ConfToJson("Server Name", Config::getServerName())); results.append(ConfToJson("Terrain Name", Config::getTerrainName())); @@ -234,13 +253,19 @@ static void data_configuration(struct mg_connection *conn, const struct mg_reque results.append(ConfToJson("Protocol Version", std::string(RORNET_VERSION))); std::string serverMode = "AUTO"; - if (Config::getServerMode() == SERVER_LAN) { + if (Config::getServerMode() == SERVER_LAN) + { results.append(ConfToJson("Server Mode", "LAN")); - } else if (Config::getServerMode() == SERVER_INET) { - if (s_is_advertised) { + } + else if (Config::getServerMode() == SERVER_INET) + { + if (s_is_advertised) + { results.append(ConfToJson("Server Mode", "Public, Internet")); results.append(ConfToJson("Server Trust Level", s_trust_level)); - } else { + } + else + { results.append(ConfToJson("Server Mode", "Private, Internet")); } } @@ -261,96 +286,115 @@ static void data_configuration(struct mg_connection *conn, const struct mg_reque results.append(ConfToJson("Webserver Port", Config::getWebserverPort())); Json::Value root; - root["ResultSet"]["Result"] = results; + root["ResultSet"]["Result"] = results; root["ResultSet"]["totalResultsAvailable"] = results.size(); - root["ResultSet"]["totalResultsReturned"] = results.size(); - root["ResultSet"]["firstResultPosition"] = 1; + root["ResultSet"]["totalResultsReturned"] = results.size(); + root["ResultSet"]["firstResultPosition"] = 1; Json::FastWriter writer; - std::string output = writer.write(root); + std::string output = writer.write(root); renderJSONHeader(conn); mg_write(conn, output.c_str(), output.size()); } -static void debug_client_list(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) { +static void debug_client_list(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) +{ } -static void data_players(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) { - Json::Value rows; +static void data_players(struct mg_connection *conn, const struct mg_request_info *request_info, void *data) +{ + Json::Value rows; - std::vector clients = s_sequencer->GetClientListCopy(); - int row_counter = 0; - for (std::vector::iterator it = clients.begin(); it != clients.end(); it++, row_counter++) { + std::vector clients = s_sequencer->GetClientListCopy(); + int row_counter = 0; + for (std::vector::iterator it = clients.begin(); it != clients.end(); it++, row_counter++) + { Json::Value row; - if (it->GetStatus() == Client::STATUS_FREE) { - row["slot"] = -1; + if (it->GetStatus() == Client::STATUS_FREE) + { + row["slot"] = -1; row["status"] = "FREE"; rows.append(row); - } else if (it->GetStatus() == Client::STATUS_BUSY) { - row["slot"] = -1; + } + else if (it->GetStatus() == Client::STATUS_BUSY) + { + row["slot"] = -1; row["status"] = "BUSY"; rows.append(row); - } else if (it->GetStatus() == Client::STATUS_USED) { + } + else if (it->GetStatus() == Client::STATUS_USED) + { // some auth identifiers std::string authst = "none"; - if (it->user.authstatus & RoRnet::AUTH_BANNED) authst = "banned"; - if (it->user.authstatus & RoRnet::AUTH_BOT) authst = "bot"; - if (it->user.authstatus & RoRnet::AUTH_RANKED) authst = "ranked"; - if (it->user.authstatus & RoRnet::AUTH_MOD) authst = "moderator"; - if (it->user.authstatus & RoRnet::AUTH_ADMIN) authst = "admin"; + if (it->user.authstatus & RoRnet::AUTH_BANNED) + authst = "banned"; + if (it->user.authstatus & RoRnet::AUTH_BOT) + authst = "bot"; + if (it->user.authstatus & RoRnet::AUTH_RANKED) + authst = "ranked"; + if (it->user.authstatus & RoRnet::AUTH_MOD) + authst = "moderator"; + if (it->user.authstatus & RoRnet::AUTH_ADMIN) + authst = "admin"; char playerColour[128] = ""; getPlayerColour(it->user.colournum, playerColour); - row["slot"] = -1; + row["slot"] = -1; row["status"] = "USED"; - row["uid"] = it->user.uniqueid; - row["ip"] = it->GetIpAddress(); - row["name"] = Str::SanitizeUtf8(it->user.username); - row["auth"] = authst; + row["uid"] = it->user.uniqueid; + row["ip"] = it->GetIpAddress(); + row["name"] = Str::SanitizeUtf8(it->user.username); + row["auth"] = authst; // get traffic stats for all streams - double bw_in = 0, bw_out = 0, bw_in_rate = 0, bw_out_rate = 0; + double bw_in = 0, bw_out = 0, bw_in_rate = 0, bw_out_rate = 0; double bw_drop_in = 0, bw_drop_out = 0, bw_drop_in_rate = 0, bw_drop_out_rate = 0; // tit = traffic iterator, not what you might think ... for (std::map::iterator tit = it->streams_traffic.begin(); - tit != it->streams_traffic.end(); tit++) { - bw_in += tit->second.bandwidthIncoming; - bw_out += tit->second.bandwidthOutgoing; - bw_in_rate += tit->second.bandwidthIncomingRate; + tit != it->streams_traffic.end(); tit++) + { + bw_in += tit->second.bandwidthIncoming; + bw_out += tit->second.bandwidthOutgoing; + bw_in_rate += tit->second.bandwidthIncomingRate; bw_out_rate += tit->second.bandwidthOutgoingRate; - bw_drop_in += tit->second.bandwidthDropIncoming; - bw_drop_out += tit->second.bandwidthDropOutgoing; - bw_drop_in_rate += tit->second.bandwidthDropIncomingRate; + bw_drop_in += tit->second.bandwidthDropIncoming; + bw_drop_out += tit->second.bandwidthDropOutgoing; + bw_drop_in_rate += tit->second.bandwidthDropIncomingRate; bw_drop_out_rate += tit->second.bandwidthDropOutgoingRate; } // traffic things - row["bw_normal_sum_up"] = formatBytes(bw_in); - row["bw_normal_sum_down"] = formatBytes(bw_out); - row["bw_normal_rate_up"] = formatBytes(bw_in_rate, true); + row["bw_normal_sum_up"] = formatBytes(bw_in); + row["bw_normal_sum_down"] = formatBytes(bw_out); + row["bw_normal_rate_up"] = formatBytes(bw_in_rate, true); row["bw_normal_rate_down"] = formatBytes(bw_out_rate, true); - row["bw_drop_sum_up"] = formatBytes(bw_drop_in); - row["bw_drop_sum_down"] = formatBytes(bw_drop_out); - row["bw_drop_rate_up"] = formatBytes(bw_drop_in_rate, true); + row["bw_drop_sum_up"] = formatBytes(bw_drop_in); + row["bw_drop_sum_down"] = formatBytes(bw_drop_out); + row["bw_drop_rate_up"] = formatBytes(bw_drop_in_rate, true); row["bw_drop_rate_down"] = formatBytes(bw_drop_out_rate, true); rows.append(row); // now add the streams themself to the table for (std::map::iterator sit = it->streams.begin(); - sit != it->streams.end(); sit++) { + sit != it->streams.end(); sit++) + { Json::Value trow; std::string typeStr = "unkown"; - if (sit->second.type == 0) typeStr = "Vehicle"; - if (sit->second.type == 1) typeStr = "Character"; - if (sit->second.type == 2) typeStr = "AI Traffic"; - if (sit->second.type == 3) typeStr = "Chat"; + if (sit->second.type == 0) + typeStr = "Vehicle"; + if (sit->second.type == 1) + typeStr = "Character"; + if (sit->second.type == 2) + typeStr = "AI Traffic"; + if (sit->second.type == 3) + typeStr = "Chat"; stream_traffic_t *traf = 0; if (it->streams_traffic.find(sit->first) != it->streams_traffic.end()) @@ -359,66 +403,72 @@ static void data_players(struct mg_connection *conn, const struct mg_request_inf char uidtmp[128] = ""; sprintf(uidtmp, "%03d:%02d", it->user.uniqueid, sit->first); - trow["slot"] = ""; + trow["slot"] = ""; trow["status"] = sit->second.status; - trow["uid"] = std::string(uidtmp); - trow["ip"] = typeStr; - trow["name"] = std::string(sit->second.name); - trow["auth"] = ""; - if (traf) { - trow["bw_normal_sum_up"] = formatBytes(traf->bandwidthIncoming); - trow["bw_normal_sum_down"] = formatBytes(traf->bandwidthOutgoing); - trow["bw_normal_rate_up"] = formatBytes(traf->bandwidthIncomingRate, true); + trow["uid"] = std::string(uidtmp); + trow["ip"] = typeStr; + trow["name"] = std::string(sit->second.name); + trow["auth"] = ""; + if (traf) + { + trow["bw_normal_sum_up"] = formatBytes(traf->bandwidthIncoming); + trow["bw_normal_sum_down"] = formatBytes(traf->bandwidthOutgoing); + trow["bw_normal_rate_up"] = formatBytes(traf->bandwidthIncomingRate, true); trow["bw_normal_rate_down"] = formatBytes(traf->bandwidthOutgoingRate, true); - trow["bw_drop_sum_up"] = formatBytes(traf->bandwidthDropIncoming); - trow["bw_drop_sum_down"] = formatBytes(traf->bandwidthDropOutgoing); - trow["bw_drop_rate_up"] = formatBytes(traf->bandwidthDropIncomingRate, true); + trow["bw_drop_sum_up"] = formatBytes(traf->bandwidthDropIncoming); + trow["bw_drop_sum_down"] = formatBytes(traf->bandwidthDropOutgoing); + trow["bw_drop_rate_up"] = formatBytes(traf->bandwidthDropIncomingRate, true); trow["bw_drop_rate_down"] = formatBytes(traf->bandwidthDropOutgoingRate, true); } rows.append(trow); } - } - } - Json::Value root; // will contains the root value after parsing. + Json::Value root; // will contains the root value after parsing. root["ResultSet"]["totalResultsAvailable"] = row_counter; - root["ResultSet"]["totalResultsReturned"] = row_counter; - root["ResultSet"]["firstResultPosition"] = 1; - root["ResultSet"]["Result"] = rows; + root["ResultSet"]["totalResultsReturned"] = row_counter; + root["ResultSet"]["firstResultPosition"] = 1; + root["ResultSet"]["Result"] = rows; Json::FastWriter writer; - std::string output = writer.write(root); + std::string output = writer.write(root); renderJSONHeader(conn); mg_write(conn, output.c_str(), output.size()); } -static void show_404(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data) { +static void show_404(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data) +{ mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n"); mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n"); mg_printf(conn, "%s", "Oops. File not found! "); } -static void signal_handler(int sig_num) { - switch (sig_num) { +static void signal_handler(int sig_num) +{ + switch (sig_num) + { #ifndef _WIN32 - case SIGCHLD: - while (waitpid(-1, &sig_num, WNOHANG) > 0); - break; -#endif /* !_WIN32 */ - case 0: - default: - break; + case SIGCHLD: + while (waitpid(-1, &sig_num, WNOHANG) > 0) + { + ; + } + break; +#endif /* !_WIN32 */ + case 0: + default: + break; } } -int StartWebserver(int port, Sequencer *sequencer, bool is_advertised, int trust_level) { +int StartWebserver(int port, Sequencer *sequencer, bool is_advertised, int trust_level) +{ s_is_advertised = is_advertised; - s_trust_level = trust_level; - s_sequencer = sequencer; + s_trust_level = trust_level; + s_sequencer = sequencer; #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); @@ -442,7 +492,8 @@ int StartWebserver(int port, Sequencer *sequencer, bool is_advertised, int trust return 0; } -int StopWebserver() { +int StopWebserver() +{ mg_stop(ctx); return 0; }