This is an automated email from the git hooks/post-receive script. apo pushed a commit to branch master in repository springlobby.
commit 7518400f4bf3ce405ec20c77989e90a4c19a0219 Author: Markus Koschany <[email protected]> Date: Sun Oct 1 19:23:46 2017 +0200 New upstream version 0.257+dfsg --- .travis.yml | 2 +- ChangeLog | 3 + VERSION | 2 +- springlobby_config.h | 2 +- src/CMakeLists.txt | 13 +- src/autohostmanager.cpp | 10 + src/autohostmanager.h | 3 + src/downloader/lib/README.md | 2 +- src/downloader/lib/src/FileSystem/FileSystem.cpp | 34 ++- src/downloader/lib/src/FileSystem/FileSystem.h | 5 +- src/downloader/lib/src/lib/minizip/unzip.c | 2 +- src/downloader/lib/src/lib/minizip/zip.c | 22 +- .../lib/src/lsl/lslunitsync/unitsync.cpp | 1 + src/downloader/lib/src/main.cpp | 41 ++-- src/downloader/lib/src/pr-downloader.cpp | 22 +- src/gui/basedataviewmodel.h | 1 - src/gui/channel/autojoinchanneldialog.cpp | 5 + src/gui/chatpanel.cpp | 1 - src/gui/connectwindow.cpp | 17 +- src/gui/connectwindow.h | 1 + src/gui/hosting/battlemaptab.cpp | 5 + src/gui/hosting/battlemaptab.h | 2 +- ...tleoptionstab.cpp => battlerestrictionstab.cpp} | 56 ++--- ...{battleoptionstab.h => battlerestrictionstab.h} | 9 +- src/gui/hosting/battleroomtab.cpp | 21 ++ src/gui/hosting/battleroomtab.h | 5 +- src/gui/hosting/mainjoinbattletab.cpp | 14 +- src/gui/hosting/mainjoinbattletab.h | 8 +- src/gui/hosting/mainsingleplayertab.cpp | 6 +- src/gui/hosting/mainsingleplayertab.h | 6 +- src/gui/mapctrl.cpp | 33 +-- src/gui/singleplayertab.cpp | 3 +- src/gui/ui.cpp | 25 ++- src/gui/ui.h | 1 + src/inetclass.h | 4 + src/serverevents.cpp | 13 +- src/serverevents.h | 1 + src/settings.cpp | 56 +++-- src/settings.h | 14 +- src/socket.cpp | 246 ++++++++++++++++++++- src/socket.h | 27 ++- src/tasserver.cpp | 31 ++- src/tasserver.h | 1 + tools/mxe_create_builddir.sh | 2 +- 44 files changed, 586 insertions(+), 192 deletions(-) diff --git a/.travis.yml b/.travis.yml index 38c1300..141fada 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ cache: ccache install: - sudo apt-get install -y libwxgtk3.0-dev libboost-thread1.55-dev libboost-system1.55-dev - - sudo apt-get install -y libboost-test1.55-dev libalure-dev cmake cmake-data + - sudo apt-get install -y libboost-test1.55-dev libalure-dev cmake cmake-data libssl-dev before_script: # optional dependencies diff --git a/ChangeLog b/ChangeLog index 1e6e152..01ac19a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ ChangeLog of Springlobby +## 0.257 + - fix unit restrictions + - add experimental tls support (default disabled) ## 0.256 - lazy init of unitsync (faster startup) diff --git a/VERSION b/VERSION index 020b4db..d6aadf1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.256 +0.257 diff --git a/springlobby_config.h b/springlobby_config.h index 85b59c4..3482b07 100644 --- a/springlobby_config.h +++ b/springlobby_config.h @@ -6,6 +6,6 @@ #undef VERSION /* the git tag / commit we build from */ -#define VERSION "0.256" +#define VERSION "0.257" #endif /* SPRINGLOBBY_HEADERGUARD_CONFIG_H */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ae57c27..8f540af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,6 +33,7 @@ endif() FIND_PACKAGE(Boost 1.42.0 COMPONENTS thread system REQUIRED) + ADD_DEFINITIONS( -DLOCALE_INSTALL_DIR="${LOCALE_INSTALL_DIR}" ) @@ -227,7 +228,7 @@ set(springlobbySrc gui/hosting/addbotdialog.cpp gui/hosting/autobalancedialog.cpp gui/hosting/battlemaptab.cpp - gui/hosting/battleoptionstab.cpp + gui/hosting/battlerestrictionstab.cpp gui/hosting/battleroomtab.cpp gui/hosting/hostbattledialog.cpp gui/hosting/mainjoinbattletab.cpp @@ -344,6 +345,16 @@ ADD_EXECUTABLE(springlobby WIN32 MACOSX_BUNDLE ${springlobby_RC_FILE} ) +FIND_PACKAGE(OpenSSL) +if(OPENSSL_FOUND) + message(STATUS "Building with OpenSSL support: ${OPENSSL_VERSION}") + target_compile_definitions(springlobby PRIVATE -DSSL_SUPPORT) + target_include_directories(springlobby PRIVATE ${OPENSSL_INCLUDE_DIR}) + target_link_libraries(springlobby ${OPENSSL_LIBRARIES}) +else() + message(WARNING "SSL support disabled!") +endif() + IF( LIBNOTIFY_FOUND AND OPTION_NOTIFY ) TARGET_LINK_LIBRARIES(springlobby ${LIBNOTIFY_LIBRARIES} ${GLIB_LIBRARIES} ) target_include_directories(springlobby PRIVATE ${LIBNOTIFY_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS}) diff --git a/src/autohostmanager.cpp b/src/autohostmanager.cpp index f2de69f..5ac5bd9 100644 --- a/src/autohostmanager.cpp +++ b/src/autohostmanager.cpp @@ -82,6 +82,11 @@ void SpringieHandler::Notify() Send("!notify"); } +void SpringieHandler::Promote() +{ + // TODO +} + void SpringieHandler::Start() { Send("!start"); @@ -129,6 +134,11 @@ void SpadsHandler::Notify() Send("!notify"); } +void SpadsHandler::Promote() +{ + Send("!promote"); +} + void SpadsHandler::Start() { Send("!start"); diff --git a/src/autohostmanager.h b/src/autohostmanager.h index 4fdf35a..342471f 100644 --- a/src/autohostmanager.h +++ b/src/autohostmanager.h @@ -19,6 +19,7 @@ public: virtual void ClearStartBoxes(){}; virtual void AddStartBox(int /*posx*/, int /*posy*/, int /*w*/, int /*h*/){}; virtual void Notify(){}; + virtual void Promote(){}; virtual void Start(){}; void SetBattle(IBattle* battle); @@ -45,6 +46,7 @@ public: void ClearStartBoxes() override; void AddStartBox(int posx, int posy, int w, int h) override; void Notify() override; + void Promote() override; void Start() override; }; @@ -60,6 +62,7 @@ public: void ClearStartBoxes() override; void AddStartBox(int posx, int posy, int w, int h) override; void Notify() override; + void Promote() override; void Start() override; }; diff --git a/src/downloader/lib/README.md b/src/downloader/lib/README.md index d4a32aa..3235e67 100644 --- a/src/downloader/lib/README.md +++ b/src/downloader/lib/README.md @@ -1,4 +1,4 @@ -#pr-downloader - tool to download maps and games for the Spring engine +# pr-downloader - tool to download maps and games for the Spring engine on the springrts.com wiki you can find [compile instructions and usage](https://springrts.com/wiki/pr-downloader). diff --git a/src/downloader/lib/src/FileSystem/FileSystem.cpp b/src/downloader/lib/src/FileSystem/FileSystem.cpp index ef6d613..57f1417 100644 --- a/src/downloader/lib/src/FileSystem/FileSystem.cpp +++ b/src/downloader/lib/src/FileSystem/FileSystem.cpp @@ -26,9 +26,12 @@ #ifndef SHGFP_TYPE_CURRENT #define SHGFP_TYPE_CURRENT 0 #endif +#else +#include <sys/statvfs.h> +#include <errno.h> #endif -CFileSystem* CFileSystem::singleton = NULL; +static CFileSystem* singleton = NULL; FILE* CFileSystem::propen(const std::string& filename, const std::string& mode) const @@ -216,8 +219,9 @@ void CFileSystem::Shutdown() tmpFileSystem = NULL; } -const std::string& CFileSystem::getSpringDir() +const std::string CFileSystem::getSpringDir() { + assert(!springdir.empty()); if (springdir.empty()) (setWritePath("")); return springdir; @@ -713,3 +717,29 @@ std::string CFileSystem::EscapeFilename(const std::string& str) } return s; } + +unsigned long CFileSystem::getMBsFree(const std::string& path) +{ +#ifdef WIN32 + ULARGE_INTEGER freespace; + BOOL res = GetDiskFreeSpaceEx(s2ws(path).c_str(), &freespace, nullptr, nullptr); + if (!res) { + LOG_ERROR("Error getting free disk space on %s: %d", path.c_str(), GetLastError()); + return 0; + } + return freespace.QuadPart / (1024 * 1024); +#else + struct statvfs st; + const int ret = statvfs(path.c_str(), &st); + if (ret != 0) { + const char *errstr = strerror(errno); + LOG_ERROR("Error getting free disk space on %s: %s", path.c_str(), errstr); + return 0; + } + if (st.f_frsize) { + return ((uint64_t)st.f_frsize * st.f_bavail) / (1024 * 1024); + } + return ((uint64_t)st.f_bsize * st.f_bavail) / (1024 * 1024); +#endif +} + diff --git a/src/downloader/lib/src/FileSystem/FileSystem.h b/src/downloader/lib/src/FileSystem/FileSystem.h index 9030c5a..0a29dff 100644 --- a/src/downloader/lib/src/FileSystem/FileSystem.h +++ b/src/downloader/lib/src/FileSystem/FileSystem.h @@ -20,8 +20,6 @@ struct _FILETIME; class CFileSystem { - static CFileSystem* singleton; - public: static CFileSystem* GetInstance(); static void Shutdown(); @@ -40,7 +38,7 @@ public: /** returns the spring writeable directory */ - const std::string& getSpringDir(); + const std::string getSpringDir(); /** checks if a directory exists @@ -136,6 +134,7 @@ public: dir/filename -> dir */ static std::string DirName(const std::string& path); + static unsigned long getMBsFree(const std::string& path); private: bool portableDownload; diff --git a/src/downloader/lib/src/lib/minizip/unzip.c b/src/downloader/lib/src/lib/minizip/unzip.c index 9093504..bcfb941 100644 --- a/src/downloader/lib/src/lib/minizip/unzip.c +++ b/src/downloader/lib/src/lib/minizip/unzip.c @@ -200,7 +200,7 @@ typedef struct /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. - IN assertion: the stream s has been sucessfully opened for reading. + IN assertion: the stream s has been successfully opened for reading. */ diff --git a/src/downloader/lib/src/lib/minizip/zip.c b/src/downloader/lib/src/lib/minizip/zip.c index ea54853..44e88a9 100644 --- a/src/downloader/lib/src/lib/minizip/zip.c +++ b/src/downloader/lib/src/lib/minizip/zip.c @@ -15,7 +15,7 @@ Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data It is used when recreting zip archive with RAW when deleting items from a zip. - ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer @@ -116,7 +116,7 @@ typedef struct linkedlist_datablock_internal_s struct linkedlist_datablock_internal_s* next_datablock; uLong avail_in_this_block; uLong filled_in_this_block; - uLong unused; /* for future use and alignement */ + uLong unused; /* for future use and alignment */ unsigned char data[SIZEDATA_INDATABLOCK]; } linkedlist_datablock_internal; @@ -171,7 +171,7 @@ typedef struct curfile64_info ci; /* info on the file curretly writing */ ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ - ZPOS64_T add_position_when_writting_offset; + ZPOS64_T add_position_when_writing_offset; ZPOS64_T number_entry; #ifndef NO_ADDFILEINEXISTINGZIP @@ -807,7 +807,7 @@ int LoadCentralDirectoryRecord(zip64_internal* pziinit) } byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); - pziinit->add_position_when_writting_offset = byte_before_the_zipfile; + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; { ZPOS64_T size_central_dir_to_read = size_central_dir; @@ -875,7 +875,7 @@ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* gl ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; - ziinit.add_position_when_writting_offset = 0; + ziinit.add_position_when_writing_offset = 0; init_linkedlist(&(ziinit.central_dir)); @@ -1164,7 +1164,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, if(zi->ci.pos_local_header >= 0xffffffff) zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); else - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); for (i=0;i<size_filename;i++) *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i); @@ -1755,7 +1755,7 @@ extern int ZEXPORT zipCloseFileInZip (zipFile file) int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; - ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); @@ -1808,7 +1808,7 @@ int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centra if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); } return err; @@ -1849,13 +1849,13 @@ int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff) { err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); } else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); } return err; @@ -1921,7 +1921,7 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment) } free_linkedlist(&(zi->central_dir)); - pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) { ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); diff --git a/src/downloader/lib/src/lsl/lslunitsync/unitsync.cpp b/src/downloader/lib/src/lsl/lslunitsync/unitsync.cpp index 27e2bcf..2df9380 100644 --- a/src/downloader/lib/src/lsl/lslunitsync/unitsync.cpp +++ b/src/downloader/lib/src/lsl/lslunitsync/unitsync.cpp @@ -575,6 +575,7 @@ StringVector Unitsync::GetUnitsList(const std::string& gamename) { assert(!gamename.empty()); StringVector cache; + GetGameHash(gamename); if (!GameExists(gamename)) return cache; const std::string cachefile = GetUnitsCacheFilePath(gamename); diff --git a/src/downloader/lib/src/main.cpp b/src/downloader/lib/src/main.cpp index 90b558f..e64a3b6 100644 --- a/src/downloader/lib/src/main.cpp +++ b/src/downloader/lib/src/main.cpp @@ -122,9 +122,35 @@ int main(int argc, char** argv) bool res = true; bool removeinvalid = false; + bool fsset = false; + while (true) { - int option_index = 0; - int c = getopt_long(argc, argv, "", long_options, &option_index); + const int c = getopt_long(argc, argv, "", long_options, nullptr); + if (c == -1) + break; + switch(c) { + case RAPID_VALIDATE_DELETE: { + removeinvalid = true; + break; + } + case FILESYSTEM_WRITEPATH: { + fsset = true; + DownloadSetConfig(CONFIG_FILESYSTEM_WRITEPATH, optarg); + break; + } + case DISABLE_LOGGING: + DownloadDisableLogging(true); + break; + default: + break; + } + } + if (!fsset) { + DownloadSetConfig(CONFIG_FILESYSTEM_WRITEPATH, ""); + } + + while (true) { + const int c = getopt_long(argc, argv, "", long_options, nullptr); if (c == -1) break; switch (c) { @@ -136,10 +162,6 @@ int main(int argc, char** argv) DownloadRapidValidate(removeinvalid); break; } - case RAPID_VALIDATE_DELETE: { - removeinvalid = true; - break; - } case FILESYSTEM_DUMPSDP: { DownloadDumpSDP(optarg); break; @@ -148,10 +170,6 @@ int main(int argc, char** argv) ValidateSDP(optarg); break; } - case FILESYSTEM_WRITEPATH: { - DownloadSetConfig(CONFIG_FILESYSTEM_WRITEPATH, optarg); - break; - } case DOWNLOAD_MAP: { if (!download(DownloadEnum::CAT_MAP, optarg)) { LOG_ERROR("No map found for %s", optarg); @@ -176,9 +194,6 @@ int main(int argc, char** argv) } break; } - case DISABLE_LOGGING: - DownloadDisableLogging(true); - break; case HELP: default: { show_help(argv[0]); diff --git a/src/downloader/lib/src/pr-downloader.cpp b/src/downloader/lib/src/pr-downloader.cpp index df56c8e..5213070 100644 --- a/src/downloader/lib/src/pr-downloader.cpp +++ b/src/downloader/lib/src/pr-downloader.cpp @@ -166,9 +166,13 @@ void DownloadShutdown() bool DownloadSetConfig(CONFIG type, const void* value) { switch (type) { - case CONFIG_FILESYSTEM_WRITEPATH: - fileSystem->setWritePath((const char*)value); + case CONFIG_FILESYSTEM_WRITEPATH: { + std::string path((const char*)value); + fileSystem->setWritePath(path); + path = fileSystem->getSpringDir(); + LOG_INFO("Free disk space: %d MB", CFileSystem::getMBsFree(path)); return true; + } case CONFIG_FETCH_DEPENDS: fetchDepends = (const bool*)value; return true; @@ -238,13 +242,27 @@ int DownloadStart() int res = 0; std::list<IDownload*> dls; std::list<int>::iterator it; + const std::string dldir = fileSystem->getSpringDir(); + const unsigned long MBsFree = CFileSystem::getMBsFree(dldir); + unsigned long dlsize = 0; for (it = downloads.begin(); it != downloads.end(); ++it) { IDownload* dl = GetIDownloadByID(searchres, *it); + if (dl->size > 0) { + dlsize += dl->size; + } if (dl == NULL) { continue; } dls.push_back(dl); } + // at least 1024MB free disk space are required (else fragmentation will make file access way to slow!) + const unsigned long MBsNeeded = (dlsize / (1024 * 1024)) + 1024; + + if (MBsFree < MBsNeeded) { + LOG_ERROR("Insuffcient free disk space (%u MiB) on %s: %u MiB needed", MBsFree, dldir.c_str(), MBsNeeded); + return 5; + } + if (fetchDepends) { addDepends(dls); } diff --git a/src/gui/basedataviewmodel.h b/src/gui/basedataviewmodel.h index 2d46804..5be269a 100644 --- a/src/gui/basedataviewmodel.h +++ b/src/gui/basedataviewmodel.h @@ -161,7 +161,6 @@ inline bool BaseDataViewModel<DataType>::IsListModel() const template <class DataType> inline bool BaseDataViewModel<DataType>::ContainsItem(const DataType& checkedItem) const { - assert(&checkedItem != nullptr); const DataType* checkItemPointer = &checkedItem; return m_ModelData.find(checkItemPointer) != m_ModelData.end(); diff --git a/src/gui/channel/autojoinchanneldialog.cpp b/src/gui/channel/autojoinchanneldialog.cpp index 72ec98c..c54644c 100644 --- a/src/gui/channel/autojoinchanneldialog.cpp +++ b/src/gui/channel/autojoinchanneldialog.cpp @@ -13,7 +13,9 @@ #include <wx/event.h> #include <wx/statline.h> #include <wx/stattext.h> +#include "servermanager.h" #include "settings.h" +#include "utils/conversion.h" BEGIN_EVENT_TABLE(AutojoinChannelDialog, wxDialog) @@ -77,6 +79,9 @@ void AutojoinChannelDialog::OnOk(wxCommandEvent& /*unused*/) else chan = line; wxString key = line.AfterFirst(_T(' ')); + + if (ServerManager::Instance()->IsConnected()) + ServerManager::Instance()->JoinChannel(STD_STRING(chan), STD_STRING(key)); sett().AddChannelJoin(chan, key); } sett().SaveSettings(); diff --git a/src/gui/chatpanel.cpp b/src/gui/chatpanel.cpp index 4eca171..6dd9b8b 100644 --- a/src/gui/chatpanel.cpp +++ b/src/gui/chatpanel.cpp @@ -830,7 +830,6 @@ const Channel* ChatPanel::GetChannel() const void ChatPanel::SetChannel(Channel* chan) { - ASSERT_LOGIC(this, "this==null"); ASSERT_LOGIC(m_type == CPT_Channel, "Not of type channel"); if ((chan == 0) && (m_channel != 0)) { diff --git a/src/gui/connectwindow.cpp b/src/gui/connectwindow.cpp index 3e9d1ca..0bf8e57 100644 --- a/src/gui/connectwindow.cpp +++ b/src/gui/connectwindow.cpp @@ -51,14 +51,17 @@ ConnectWindow::ConnectWindow(wxWindow* parent, Ui& ui) wxString password; bool savepass; bool autoconnect; + bool tls; SetIcon(wxIcon(connect_xpm)); server = sett().GetDefaultServer(); - username = sett().GetServerAccountNick(sett().GetDefaultServer()); - password = sett().GetServerAccountPass(sett().GetDefaultServer()); - savepass = sett().GetServerAccountSavePass(sett().GetDefaultServer()); + username = sett().GetServerAccountNick(server); + password = sett().GetServerAccountPass(server); + savepass = sett().GetServerAccountSavePass(server); autoconnect = cfg().ReadBool(_T( "/Server/Autoconnect" )); + tls = sett().IsServerTLS(STD_STRING(server)); + // Create all UI elements. m_tabs = new wxNotebook(this, -1); m_login_tab = new wxPanel(m_tabs, -1); @@ -78,8 +81,12 @@ ConnectWindow::ConnectWindow(wxWindow* parent, Ui& ui) m_autoconnect_check = new wxCheckBox(m_login_tab, -1, _("Autoconnect next time")); m_autoconnect_check->SetToolTip(_("remember connection details and automatically connect to server on next lobby startup")); + m_tls_check = new wxCheckBox(m_login_tab, -1, _("TLS")); + m_tls_check->SetToolTip(_("Use encrypted connection to connect to the Lobby server")); + m_rpass_check->SetValue(savepass); m_autoconnect_check->SetValue(autoconnect); + m_tls_check->SetValue(tls); m_acc_note_line = new wxStaticLine(m_login_tab); @@ -111,6 +118,7 @@ ConnectWindow::ConnectWindow(wxWindow* parent, Ui& ui) m_rpass_sizer->Add(m_rpass_check, 2, wxEXPAND | wxALL | wxALIGN_RIGHT, 4); m_rpass_sizer->Add(m_autoconnect_check, 2, wxEXPAND | wxALL | wxALIGN_RIGHT, 4); + m_rpass_sizer->Add(m_tls_check, 2, wxEXPAND | wxALL | wxALIGN_RIGHT, 4); m_pass_sizer->Add(m_pass_lbl, 1, wxALL | wxALIGN_CENTER_VERTICAL, 4); m_pass_sizer->Add(m_pass_text, 2, wxEXPAND | wxALL, 4); @@ -255,10 +263,11 @@ void ConnectWindow::OnOk(wxCommandEvent&) OnLoginDenied(_T("Port number out of range.\n\nIt must be an integer between 1 and 65535")); return; } - sett().SetServer(HostAddress, serverString[0], port); + sett().SetServer(HostAddress, serverString[0], port, ""); } sett().SetDefaultServer(HostAddress); cfg().Write(_T( "/Server/Autoconnect" ), m_autoconnect_check->IsChecked()); + sett().SetServerTLS(STD_STRING(HostAddress), m_tls_check->IsChecked()); //if autoconnect enabled force saving of pw, actual saving is done in Ui::DoConnect diff --git a/src/gui/connectwindow.h b/src/gui/connectwindow.h index 5222344..fa1fc6f 100644 --- a/src/gui/connectwindow.h +++ b/src/gui/connectwindow.h @@ -57,6 +57,7 @@ private: wxTextCtrl* m_pass_text; //!< Textbox where user can input password wxCheckBox* m_rpass_check; //!< Checkbox where user can chose if he wants his password to be saved. wxCheckBox* m_autoconnect_check; //!< Checkbox where user can chose if he wants to autoconnect. + wxCheckBox* m_tls_check; //!< Checkbox where user can chose if he wants the connection to be encrypted. wxStaticLine* m_acc_note_line; //!< Line that separates the account settings from the note diff --git a/src/gui/hosting/battlemaptab.cpp b/src/gui/hosting/battlemaptab.cpp index 55155e9..be1dfc4 100644 --- a/src/gui/hosting/battlemaptab.cpp +++ b/src/gui/hosting/battlemaptab.cpp @@ -169,6 +169,11 @@ void BattleMapTab::Update(const wxString& Tag) { if (!m_battle) return; + if (Tag.empty()) { + Update(); + return; + } + long type; Tag.BeforeFirst('_').ToLong(&type); const std::string key = STD_STRING(Tag.AfterFirst('_')); diff --git a/src/gui/hosting/battlemaptab.h b/src/gui/hosting/battlemaptab.h index 4f002ef..f3ad2d4 100644 --- a/src/gui/hosting/battlemaptab.h +++ b/src/gui/hosting/battlemaptab.h @@ -33,7 +33,6 @@ public: void UpdateUser(User& user); - void Update(); void Update(const wxString& Tag); void ReloadMaplist(); @@ -45,6 +44,7 @@ private: { return m_battle; } + void Update(); void OnMapSelect(wxCommandEvent& event); void OnMapBrowse(wxCommandEvent& event); void OnStartTypeSelect(wxCommandEvent& event); diff --git a/src/gui/hosting/battleoptionstab.cpp b/src/gui/hosting/battlerestrictionstab.cpp similarity index 83% rename from src/gui/hosting/battleoptionstab.cpp rename to src/gui/hosting/battlerestrictionstab.cpp index ebdc1a1..253fb6f 100644 --- a/src/gui/hosting/battleoptionstab.cpp +++ b/src/gui/hosting/battlerestrictionstab.cpp @@ -1,10 +1,10 @@ /* This file is part of the Springlobby (GPL v2 or later), see COPYING */ // -// Class: BattleOptionsTab +// Class: BattleRestrictionsTab // -#include "battleoptionstab.h" +#include "battlerestrictionstab.h" #include <wx/splitter.h> #include <wx/intl.h> @@ -20,7 +20,6 @@ #include <wx/checklst.h> #include <wx/numdlg.h> -#include "battleoptionstab.h" #include "ibattle.h" #include "gui/controls.h" #include "utils/conversion.h" @@ -31,16 +30,16 @@ #include "aui/auimanager.h" -BEGIN_EVENT_TABLE(BattleOptionsTab, wxPanel) +BEGIN_EVENT_TABLE(BattleRestrictionsTab, wxPanel) -EVT_BUTTON(BOPTS_RESTRICT, BattleOptionsTab::OnRestrict) -EVT_BUTTON(BOPTS_ALLOW, BattleOptionsTab::OnAllow) -EVT_BUTTON(BOPTS_CLEARRES, BattleOptionsTab::OnClearRestrictions) +EVT_BUTTON(BOPTS_RESTRICT, BattleRestrictionsTab::OnRestrict) +EVT_BUTTON(BOPTS_ALLOW, BattleRestrictionsTab::OnAllow) +EVT_BUTTON(BOPTS_CLEARRES, BattleRestrictionsTab::OnClearRestrictions) END_EVENT_TABLE() -BattleOptionsTab::BattleOptionsTab(wxWindow* parent, IBattle* battle) +BattleRestrictionsTab::BattleRestrictionsTab(wxWindow* parent, IBattle* battle) : wxScrolledWindow(parent, -1) , m_battle(battle) { @@ -114,27 +113,14 @@ BattleOptionsTab::BattleOptionsTab(wxWindow* parent, IBattle* battle) } -BattleOptionsTab::~BattleOptionsTab() +BattleRestrictionsTab::~BattleRestrictionsTab() { if (GetAui().manager) GetAui().manager->DetachPane(this); } -void BattleOptionsTab::UpdateBattle(const wxString& Tag) -{ - if (!m_battle) - return; - long type; - Tag.BeforeFirst('_').ToLong(&type); - wxString key = Tag.AfterFirst('_'); - if (type == LSL::Enum::PrivateOptions) { - if (key == _T( "restrictions" )) - ReloadRestrictions(); - } -} - -void BattleOptionsTab::ReloadRestrictions() +void BattleRestrictionsTab::ReloadRestrictions() { if (!m_battle) return; @@ -155,7 +141,7 @@ void BattleOptionsTab::ReloadRestrictions() } -int BattleOptionsTab::GetAllowedUnitIndex(const wxString& name) +int BattleRestrictionsTab::GetAllowedUnitIndex(const wxString& name) { if (!m_battle) return -1; @@ -170,7 +156,7 @@ int BattleOptionsTab::GetAllowedUnitIndex(const wxString& name) } -int BattleOptionsTab::GetRestrictedUnitIndex(const wxString& name) +int BattleRestrictionsTab::GetRestrictedUnitIndex(const wxString& name) { if (!m_battle) return -1; @@ -185,13 +171,13 @@ int BattleOptionsTab::GetRestrictedUnitIndex(const wxString& name) } -bool BattleOptionsTab::IsRestricted(const wxString& name) +bool BattleRestrictionsTab::IsRestricted(const wxString& name) { return (GetRestrictedUnitIndex(name) >= 0); } -void BattleOptionsTab::Restrict(const wxString& name, int count) +void BattleRestrictionsTab::Restrict(const wxString& name, int count) { if (!m_battle) return; @@ -200,7 +186,7 @@ void BattleOptionsTab::Restrict(const wxString& name, int count) } -void BattleOptionsTab::Allow(const wxString& name) +void BattleRestrictionsTab::Allow(const wxString& name) { if (!m_battle) return; @@ -209,7 +195,7 @@ void BattleOptionsTab::Allow(const wxString& name) } -void BattleOptionsTab::Restrict(int index, int count) +void BattleRestrictionsTab::Restrict(int index, int count) { if (!m_battle) return; @@ -221,7 +207,7 @@ void BattleOptionsTab::Restrict(int index, int count) } -void BattleOptionsTab::Allow(int index) +void BattleRestrictionsTab::Allow(int index) { if (!m_battle) return; @@ -238,7 +224,7 @@ void BattleOptionsTab::Allow(int index) ////////////////////////////////////////////////////////////////////////// -void BattleOptionsTab::OnRestrict(wxCommandEvent& /*unused*/) +void BattleRestrictionsTab::OnRestrict(wxCommandEvent& /*unused*/) { if (!m_battle) return; @@ -263,7 +249,7 @@ void BattleOptionsTab::OnRestrict(wxCommandEvent& /*unused*/) } -void BattleOptionsTab::OnAllow(wxCommandEvent& /*unused*/) +void BattleRestrictionsTab::OnAllow(wxCommandEvent& /*unused*/) { if (!m_battle) return; @@ -286,7 +272,7 @@ void BattleOptionsTab::OnAllow(wxCommandEvent& /*unused*/) } -void BattleOptionsTab::OnClearRestrictions(wxCommandEvent& /*unused*/) +void BattleRestrictionsTab::OnClearRestrictions(wxCommandEvent& /*unused*/) { if (!m_battle) return; @@ -294,7 +280,7 @@ void BattleOptionsTab::OnClearRestrictions(wxCommandEvent& /*unused*/) ReloadRestrictions(); } -void BattleOptionsTab::SetBattle(IBattle* battle) +void BattleRestrictionsTab::SetBattle(IBattle* battle) { m_battle = battle; bool isBattleEnabled = (battle != nullptr); @@ -316,7 +302,7 @@ void BattleOptionsTab::SetBattle(IBattle* battle) } } -IBattle* BattleOptionsTab::GetBattle() +IBattle* BattleRestrictionsTab::GetBattle() { return m_battle; } diff --git a/src/gui/hosting/battleoptionstab.h b/src/gui/hosting/battlerestrictionstab.h similarity index 89% rename from src/gui/hosting/battleoptionstab.h rename to src/gui/hosting/battlerestrictionstab.h index c9a35da..5599253 100644 --- a/src/gui/hosting/battleoptionstab.h +++ b/src/gui/hosting/battlerestrictionstab.h @@ -19,13 +19,12 @@ class wxCheckListBox; /** \brief manipulate "standard" engine options, unit restriction list * \todo DOCMEMORE */ -class BattleOptionsTab : public wxScrolledWindow +class BattleRestrictionsTab : public wxScrolledWindow { public: - BattleOptionsTab(wxWindow* parent, IBattle* battle); - ~BattleOptionsTab(); + BattleRestrictionsTab(wxWindow* parent, IBattle* battle); + ~BattleRestrictionsTab(); - void UpdateBattle(const wxString& Tag); void ReloadRestrictions(); void SetBattle(IBattle* battle); @@ -44,8 +43,6 @@ private: void OnAllow(wxCommandEvent& event); void OnClearRestrictions(wxCommandEvent& event); - void UpdateBattle(); - IBattle* m_battle; wxStaticText* m_aloowed_lbl; diff --git a/src/gui/hosting/battleroomtab.cpp b/src/gui/hosting/battleroomtab.cpp index a8cabc5..7233ad1 100644 --- a/src/gui/hosting/battleroomtab.cpp +++ b/src/gui/hosting/battleroomtab.cpp @@ -63,6 +63,7 @@ BEGIN_EVENT_TABLE(BattleRoomTab, wxPanel) +EVT_BUTTON(BROOM_PROMOTE, BattleRoomTab::OnPromote) EVT_BUTTON(BROOM_START, BattleRoomTab::OnStart) EVT_BUTTON(BROOM_LEAVE, BattleRoomTab::OnLeave) EVT_BUTTON(BROOM_ADDBOT, BattleRoomTab::OnAddBot) @@ -180,6 +181,8 @@ BattleRoomTab::BattleRoomTab(wxWindow* parent, IBattle* battle) m_host_new_btn->SetToolTip(_("Host a new battle")); m_leave_btn = new wxButton(this, BROOM_LEAVE, _("Leave"), wxDefaultPosition, wxSize(-1, CONTROL_HEIGHT)); m_leave_btn->SetToolTip(_("Leave the battle and return to the battle list")); + m_promote_btn = new wxButton(this, BROOM_PROMOTE, _("Promote"), wxDefaultPosition, wxSize(-1, CONTROL_HEIGHT)); + m_promote_btn->SetToolTip(_("Promote the battle in some chat channels")); m_start_btn = new wxButton(this, BROOM_START, _("Start"), wxDefaultPosition, wxSize(-1, CONTROL_HEIGHT)); m_start_btn->SetToolTip(_("Start the battle")); @@ -347,6 +350,7 @@ BattleRoomTab::BattleRoomTab(wxWindow* parent, IBattle* battle) m_buttons_sizer->Add(m_autolock_chk, 0, wxEXPAND | wxALL, 2); m_buttons_sizer->Add(m_lock_chk, 0, wxEXPAND | wxALL, 2); m_buttons_sizer->Add(m_manage_players_btn, 0, wxEXPAND | wxALL, 2); + m_buttons_sizer->Add(m_promote_btn, 0, wxEXPAND | wxALL, 2); m_buttons_sizer->Add(m_start_btn, 0, wxEXPAND | wxALL, 2); m_main_sizer->Add(m_top_sizer, 1, wxEXPAND); @@ -446,6 +450,10 @@ void BattleRoomTab::UpdateBattleInfo(const wxString& Tag) { if (!m_battle) return; + if (Tag.empty()) { + UpdateBattleInfo(); + return; + } if (m_opt_list_map.find(Tag) == m_opt_list_map.end()) { wxLogWarning("Tag %s not found in options list", STD_STRING(Tag).c_str()); @@ -592,6 +600,18 @@ ChatPanel& BattleRoomTab::GetChatPanel() return *m_chat; } +void BattleRoomTab::OnPromote(wxCommandEvent& /*unused*/) +{ + if (!m_battle) + return; + + if (m_battle->IsFounderMe()) { + customMessageBoxModal(SL_MAIN_ICON, _("You need to be in an autohost for this to work."), _("Error")); + } else { + m_battle->m_autohost_manager->GetAutohostHandler().Promote(); + } +} + void BattleRoomTab::OnStart(wxCommandEvent& /*unused*/) { if (!m_battle) @@ -1152,6 +1172,7 @@ void BattleRoomTab::SetBattle(IBattle* battle) m_players->Enable(isBattleEnabled); m_leave_btn->Enable(isBattleEnabled); + m_promote_btn->Enable(isBattleEnabled); m_start_btn->Enable(isBattleEnabled); m_addbot_btn->Enable(isBattleEnabled); m_manage_players_btn->Enable(isBattleEnabled); diff --git a/src/gui/hosting/battleroomtab.h b/src/gui/hosting/battleroomtab.h index 7d1e04d..ac55d08 100644 --- a/src/gui/hosting/battleroomtab.h +++ b/src/gui/hosting/battleroomtab.h @@ -48,7 +48,6 @@ public: IBattle* GetBattle(); ChatPanel& GetChatPanel(); - void UpdateBattleInfo(); void UpdateBattleInfo(const wxString& Tag); @@ -71,10 +70,12 @@ public: void PrintAllySetup(); private: + void UpdateBattleInfo(); void RegenerateOptionsList(); void UpdateStatsLabels(); void UpdateMapInfoSummary(); + void OnPromote(wxCommandEvent& event); void OnStart(wxCommandEvent& event); void OnHostNew(wxCommandEvent& event); void OnLeave(wxCommandEvent& event); @@ -177,6 +178,7 @@ private: wxStaticLine* m_command_line; wxButton* m_leave_btn; + wxButton* m_promote_btn; wxButton* m_start_btn; wxButton* m_addbot_btn; wxButton* m_manage_players_btn; @@ -216,6 +218,7 @@ private: BROOM_ALLYSEL, BROOM_COLOURSEL, BROOM_SIDESEL, + BROOM_PROMOTE, BROOM_START, BROOM_ADDBOT, BROOM_BALANCE, diff --git a/src/gui/hosting/mainjoinbattletab.cpp b/src/gui/hosting/mainjoinbattletab.cpp index 61580af..f5cb531 100644 --- a/src/gui/hosting/mainjoinbattletab.cpp +++ b/src/gui/hosting/mainjoinbattletab.cpp @@ -16,7 +16,7 @@ #include "mainjoinbattletab.h" #include "battleroomtab.h" #include "battlemaptab.h" -#include "battleoptionstab.h" +#include "battlerestrictionstab.h" #include "utils/conversion.h" #include "battleroommmoptionstab.h" #include "aui/auimanager.h" @@ -60,7 +60,7 @@ MainJoinBattleTab::MainJoinBattleTab(wxWindow* parent) m_mm_opts_tab = new BattleroomMMOptionsTab(0, m_tabs); m_tabs->InsertPage(2, m_mm_opts_tab, _("Options"), false, wxIcon(battle_settings_xpm)); - m_opts_tab = new BattleOptionsTab(m_tabs, 0); + m_opts_tab = new BattleRestrictionsTab(m_tabs, 0); m_tabs->InsertPage(3, m_opts_tab, _("Unit Restrictions"), false, wxIcon(battle_settings_xpm)); m_main_sizer->Add(m_tabs, 1, wxEXPAND); @@ -89,17 +89,11 @@ ChatPanel* MainJoinBattleTab::GetActiveChatPanel() return NULL; } -void MainJoinBattleTab::UpdateCurrentBattle() -{ - GetBattleRoomTab().UpdateBattleInfo(); - GetBattleMapTab().Update(); -} - void MainJoinBattleTab::UpdateCurrentBattle(const wxString& Tag) { GetBattleRoomTab().UpdateBattleInfo(Tag); GetBattleMapTab().Update(Tag); - GetOptionsTab().UpdateBattle(Tag); + GetOptionsTab().ReloadRestrictions(); GetMMOptionsTab().UpdateOptControls(Tag); } @@ -166,7 +160,7 @@ BattleMapTab& MainJoinBattleTab::GetBattleMapTab() } -BattleOptionsTab& MainJoinBattleTab::GetOptionsTab() +BattleRestrictionsTab& MainJoinBattleTab::GetOptionsTab() { ASSERT_EXCEPTION(m_opts_tab, _T( "m_opts_tab == 0" )); return *m_opts_tab; diff --git a/src/gui/hosting/mainjoinbattletab.h b/src/gui/hosting/mainjoinbattletab.h index 153e7d1..631ef07 100644 --- a/src/gui/hosting/mainjoinbattletab.h +++ b/src/gui/hosting/mainjoinbattletab.h @@ -10,7 +10,7 @@ class IBattle; class User; class BattleRoomTab; class BattleMapTab; -class BattleOptionsTab; +class BattleRestrictionsTab; class wxBoxSizer; class wxImageList; class SLNotebook; @@ -25,8 +25,6 @@ public: void HostBattle(IBattle& battle); void JoinBattle(IBattle& battle); - //void UpdateCurrentBattle(); - void UpdateCurrentBattle(); void UpdateCurrentBattle(const wxString& Tag); void LeaveCurrentBattle(bool called_from_join = false); void OnDisconnected() @@ -47,7 +45,7 @@ public: private: BattleMapTab& GetBattleMapTab(); - BattleOptionsTab& GetOptionsTab(); + BattleRestrictionsTab& GetOptionsTab(); BattleroomMMOptionsTab& GetMMOptionsTab(); wxBoxSizer* m_main_sizer; @@ -57,7 +55,7 @@ private: BattleRoomTab* m_battle_tab; BattleMapTab* m_map_tab; - BattleOptionsTab* m_opts_tab; + BattleRestrictionsTab* m_opts_tab; BattleroomMMOptionsTab* m_mm_opts_tab; enum { diff --git a/src/gui/hosting/mainsingleplayertab.cpp b/src/gui/hosting/mainsingleplayertab.cpp index 4a6d93a..6267479 100644 --- a/src/gui/hosting/mainsingleplayertab.cpp +++ b/src/gui/hosting/mainsingleplayertab.cpp @@ -12,7 +12,7 @@ #include "aui/auimanager.h" #include "gui/slbook.h" #include "gui/singleplayertab.h" -#include "gui/hosting/battleoptionstab.h" +#include "gui/hosting/battlerestrictionstab.h" #include "gui/hosting/mainsingleplayertab.h" #include "gui/hosting/battleroommmoptionstab.h" #include "utils/conversion.h" @@ -39,7 +39,7 @@ MainSinglePlayerTab::MainSinglePlayerTab(wxWindow* parent) m_tabs->AddPage(m_sp_tab, _("Game"), true, wxNullBitmap); m_mm_opts_tab = new BattleroomMMOptionsTab(&m_sp_tab->GetBattle(), m_tabs); m_tabs->InsertPage(1, m_mm_opts_tab, _("Options"), false, wxIcon(battle_settings_xpm)); - m_opts_tab = new BattleOptionsTab(m_tabs, &m_sp_tab->GetBattle()); + m_opts_tab = new BattleRestrictionsTab(m_tabs, &m_sp_tab->GetBattle()); m_tabs->InsertPage(2, m_opts_tab, _("Unit Restrictions"), false, wxIcon(battle_settings_xpm)); m_main_sizer->Add(m_tabs, 1, wxEXPAND); @@ -123,7 +123,7 @@ SinglePlayerTab& MainSinglePlayerTab::GetSinglePlayerTab() return *m_sp_tab; } -BattleOptionsTab& MainSinglePlayerTab::GetOptionsTab() +BattleRestrictionsTab& MainSinglePlayerTab::GetOptionsTab() { ASSERT_EXCEPTION(m_opts_tab, _T( "m_opts_tab == 0" )); return *m_opts_tab; diff --git a/src/gui/hosting/mainsingleplayertab.h b/src/gui/hosting/mainsingleplayertab.h index 35c8394..ce0ad11 100644 --- a/src/gui/hosting/mainsingleplayertab.h +++ b/src/gui/hosting/mainsingleplayertab.h @@ -11,7 +11,7 @@ class SLNotebook; class wxImageList; class wxBoxSizer; class SinglePlayerTab; -class BattleOptionsTab; +class BattleRestrictionsTab; class MainSinglePlayerTab : public wxPanel { @@ -28,7 +28,7 @@ public: void ReloadPresetList(); SinglePlayerTab& GetSinglePlayerTab(); - BattleOptionsTab& GetOptionsTab(); + BattleRestrictionsTab& GetOptionsTab(); BattleroomMMOptionsTab& GetMMOptionsTab(); void LoadPerspective(const wxString& perspective_name = wxEmptyString); @@ -40,7 +40,7 @@ private: SLNotebook* m_tabs; SinglePlayerTab* m_sp_tab; - BattleOptionsTab* m_opts_tab; + BattleRestrictionsTab* m_opts_tab; BattleroomMMOptionsTab* m_mm_opts_tab; }; diff --git a/src/gui/mapctrl.cpp b/src/gui/mapctrl.cpp index 1bd2f6e..705ffd2 100644 --- a/src/gui/mapctrl.cpp +++ b/src/gui/mapctrl.cpp @@ -1013,8 +1013,6 @@ void MapCtrl::DrawUserPositions(wxDC& dc) User* bot = 0; for (unsigned int bi = 0; bi < m_battle->GetNumUsers(); bi++) { User& tbot = m_battle->GetUser(bi); - if (&tbot == 0) - continue; if (tbot.BattleStatus().spectator) continue; if ((tbot.BattleStatus().pos.x == m_map.info.positions[i].x) && (tbot.BattleStatus().pos.y == m_map.info.positions[i].y)) { @@ -1031,8 +1029,6 @@ void MapCtrl::DrawUserPositions(wxDC& dc) int previousteam = -1; for (unsigned int i = 0; i < m_battle->GetNumUsers(); i++) { User& usr = m_battle->GetUser(i); - if (&usr == 0) - continue; if (usr.BattleStatus().spectator) continue; int currentteam = usr.BattleStatus().team; @@ -1111,11 +1107,6 @@ void MapCtrl::OnMouseMove(wxMouseEvent& event) return; if (m_maction == Moved) { User& user = *m_user_expanded; - try { - ASSERT_LOGIC(&user != 0, "MapCtrl::OnMouseMove(): user = 0"); - } catch (...) { - return; - } m_map = m_battle->LoadMap(); wxRect mr = GetMinimapRect(); @@ -1141,13 +1132,8 @@ void MapCtrl::OnMouseMove(wxMouseEvent& event) if (!m_user_expanded || !m_battle->UserExists(m_user_expanded->GetNick())) m_user_expanded = 0; - if (m_user_expanded) { + if (m_user_expanded != nullptr) { User& user = *m_user_expanded; - try { - ASSERT_LOGIC(&user != 0, "MapCtrl::OnMouseMove(): user = 0"); - } catch (...) { - return; - } wxRect r = GetUserRect(user, true); if (r.Contains(event.GetX(), event.GetY())) { RectangleArea last = m_rect_area; @@ -1161,8 +1147,6 @@ void MapCtrl::OnMouseMove(wxMouseEvent& event) } else { for (unsigned int i = 0; i < m_battle->GetNumUsers(); i++) { User& user = m_battle->GetUser(i); - if (&user == 0) - continue; wxRect r = GetUserRect(user, false); if (r.Contains(event.GetX(), event.GetY())) { m_rect_area = GetUserRectArea(r, event.GetX(), event.GetY()); @@ -1317,12 +1301,9 @@ void MapCtrl::OnLeftDown(wxMouseEvent& event) m_maction = Moved; else m_maction = None; - User& user = *m_user_expanded; - try { - ASSERT_LOGIC(&user != 0, "MapCtrl::OnLeftDown(): user = 0"); - } catch (...) { + if (m_user_expanded == nullptr) return; - } + User& user = *m_user_expanded; RefreshRect(GetUserRect(user, true), false); return; } @@ -1390,16 +1371,11 @@ void MapCtrl::OnLeftUp(wxMouseEvent& event) const long longval = LSL::Util::FromIntString(m_battle->CustomBattleOptions() .getSingleValue("startpostype", LSL::Enum::EngineOption)); if (longval == IBattle::ST_Pick) { - if (!m_user_expanded) + if (m_user_expanded == nullptr) return; if (m_rect_area != m_mdown_area) return; User& user = *m_user_expanded; - try { - ASSERT_LOGIC(&user != 0, "MapCtrl::OnLeftUp(): user == 0"); - } catch (...) { - return; - } if ((m_mdown_area == Move) && (m_maction == Moved)) { m_battle->UserPositionChanged(user); } else if (m_mdown_area == UpAllyButton) { @@ -1531,7 +1507,6 @@ void MapCtrl::OnRightUp(wxMouseEvent& event) bs.ally = m_battle->GetFreeAlly(); bs.colour = m_battle->GetNewColour(); User& bot = m_battle->OnBotAdded(STD_STRING(dlg.GetNick()), bs); - ASSERT_LOGIC(&bot != 0, "bot == 0"); bot.BattleStatus().pos.x = x; bot.BattleStatus().pos.y = y; RefreshRect(GetUserRect(bot, false), false); diff --git a/src/gui/singleplayertab.cpp b/src/gui/singleplayertab.cpp index 8685fed..0d03b84 100644 --- a/src/gui/singleplayertab.cpp +++ b/src/gui/singleplayertab.cpp @@ -399,8 +399,7 @@ void SinglePlayerTab::OnAddBot(wxCommandEvent& /*unused*/) bs.team = m_battle.GetFreeTeam(); bs.ally = m_battle.GetFreeAlly(); bs.colour = m_battle.GetNewColour(); - User& bot = m_battle.OnBotAdded(STD_STRING(dlg.GetNick()), bs); - ASSERT_LOGIC(&bot != 0, "bot == 0"); + m_battle.OnBotAdded(STD_STRING(dlg.GetNick()), bs); m_minimap->UpdateMinimap(); } } diff --git a/src/gui/ui.cpp b/src/gui/ui.cpp index 98cac82..46a0c68 100644 --- a/src/gui/ui.cpp +++ b/src/gui/ui.cpp @@ -66,6 +66,7 @@ SLCONFIG("/General/LastUpdateCheck", 0L, "Last time springlobby checked for an u SLCONFIG("/GUI/StartTab", (long)MainWindow::PAGE_SINGLE, "which tab to show on startup"); SLCONFIG("/Chat/BroadcastEverywhere", true, "setting to spam the server messages in all channels"); SLCONFIG("/Server/Autoconnect", false, "Connect to server on startup"); +SLCONFIG("/Server/TLS", false, "Use encrypted connection to the lobby server"); static unsigned int s_reconnect_delay_ms = 6 * 1000; //initial reconnect delay @@ -319,10 +320,6 @@ void Ui::OnDisconnected(IServer& server, bool wasonline) if (m_main_win == 0) return; slLogDebugFunc(""); - if (!&server) { - wxLogError(_T("WTF got null reference!!!")); - return; - } mw().GetJoinTab().OnDisconnected(); mw().GetBattleListTab().OnDisconnected(); @@ -592,10 +589,7 @@ void Ui::OnBattleInfoUpdated(IBattle& battle, const wxString& Tag) return; mw().GetBattleListTab().UpdateBattle(battle); if (mw().GetJoinTab().GetCurrentBattle() == &battle) { - if (Tag.IsEmpty()) - mw().GetJoinTab().UpdateCurrentBattle(); - else - mw().GetJoinTab().UpdateCurrentBattle(Tag); + mw().GetJoinTab().UpdateCurrentBattle(Tag); } } @@ -968,3 +962,18 @@ bool Ui::NeedsDownload(const IBattle* battle, bool uiprompt, DownloadEnum::Categ return true; } + +void Ui::OnInvalidFingerprintReceived(const std::string& fingerprint, const std::string& expected_fingerprint) +{ + int answer = wxCANCEL; + if (expected_fingerprint.empty()) { + answer = customMessageBox(SL_MAIN_ICON, _("The certificate by the server is unkown. Do you want to trust it? Please verify the fingerprint:\n") + TowxString(fingerprint) , _("Unknown Certificate"), wxYES_NO | wxCANCEL); + } else { + answer = customMessageBox(SL_MAIN_ICON, _("The certificate by the server is invalid! Maybe there is a MITM ongoing. Do you want ignore this warning?:\n") + TowxString(fingerprint) , _("Unknown Certificate"), wxYES_NO | wxCANCEL); + } + if (answer != wxYES) { + return; + } + + sett().SetServerFingerprint(m_serv->GetServerName(), fingerprint); +} diff --git a/src/gui/ui.h b/src/gui/ui.h index df69e2d..a1d2e0a 100644 --- a/src/gui/ui.h +++ b/src/gui/ui.h @@ -118,6 +118,7 @@ public: void FirstRunWelcome(); void CheckForUpdates(bool show); void EnableDebug(bool enable); + void OnInvalidFingerprintReceived(const std::string& fingerprint, const std::string& expected_fingerprint); private: void OnLobbyDownloaded(wxCommandEvent& /*data*/); diff --git a/src/inetclass.h b/src/inetclass.h index 7516a94..45ece42 100644 --- a/src/inetclass.h +++ b/src/inetclass.h @@ -33,6 +33,10 @@ public: virtual void Ping() { } + + virtual void OnInvalidFingerprintReceived(const std::string& /*fingerprint*/) + { + } }; #endif // SPRINGLOBBY_HEADERGUARD_INETCLASS_H diff --git a/src/serverevents.cpp b/src/serverevents.cpp index 5ff6d4b..e2c33d7 100644 --- a/src/serverevents.cpp +++ b/src/serverevents.cpp @@ -403,6 +403,7 @@ void ServerEvents::OnBattleInfoUpdated(int battleid, int spectators, bool locked ui().OnBattleInfoUpdated(battle, wxEmptyString); } catch (assert_exception) { + wxLogWarning("Exception in OnBattleInfoUpdated"); } } @@ -553,6 +554,7 @@ void ServerEvents::OnBattleInfoUpdated(int battleid) IBattle& battle = m_serv.GetBattle(battleid); ui().OnBattleInfoUpdated(battle, wxEmptyString); } catch (assert_exception) { + wxLogWarning("Exception in OnBattleInfoUpdated(%d)", battleid); } } @@ -576,6 +578,7 @@ void ServerEvents::OnBattleDisableUnit(int battleid, const std::string& unitname try { IBattle& battle = m_serv.GetBattle(battleid); battle.RestrictUnit(unitname, count); + wxLogDebug("OnBattleDisableUnit %d %s %d", battleid, unitname.c_str(), count); } catch (assert_exception) { } } @@ -775,7 +778,6 @@ void ServerEvents::OnBattleAddBot(int battleid, const std::string& nick, UserBat IBattle& battle = m_serv.GetBattle(battleid); battle.OnBotAdded(nick, status); User& bot = battle.GetUser(nick); - ASSERT_LOGIC(&bot != 0, "Bot null after add."); ui().OnUserJoinedBattle(battle, bot); } catch (assert_exception) { } @@ -900,7 +902,7 @@ void ServerEvents::OnKickedFromBattle() void ServerEvents::OnRedirect(const std::string& address, unsigned int port, const std::string& CurrentNick, const std::string& CurrentPassword) { const std::string name = stdprintf("%s:%d", address.c_str(), port); - sett().SetServer(name, TowxString(address), port); + sett().SetServer(name, TowxString(address), port, ""); //TODO: Rework this. Server calls it`s own method through another object! ServerManager::Instance()->DoConnectToServer(name, CurrentNick, CurrentPassword); } @@ -999,3 +1001,10 @@ void ServerEvents::OnLoginDenied(const std::string& reason) { ui().OnLoginDenied(reason); } + +void ServerEvents::OnInvalidFingerprintReceived(const std::string& fingerprint, const std::string& expected_fingerprint) +{ + ui().OnInvalidFingerprintReceived(fingerprint, expected_fingerprint); +} + + diff --git a/src/serverevents.h b/src/serverevents.h index e6c19a0..40890ec 100644 --- a/src/serverevents.h +++ b/src/serverevents.h @@ -130,6 +130,7 @@ public: void RegistrationAccepted(const std::string& user, const std::string& pass); void RegistrationDenied(const std::string& reason); void OnLoginDenied(const std::string& reason); + void OnInvalidFingerprintReceived(const std::string& fingerprint, const std::string& expected_fingerprint); private: IServer& m_serv; diff --git a/src/settings.cpp b/src/settings.cpp index c354d5e..8e0bb8d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -35,6 +35,8 @@ const wxChar sep = wxFileName::GetPathSeparator(); const wxString sepstring = wxString(sep); +const long CACHE_VERSION = 15; +const long SETTINGS_VERSION = 32; SLCONFIG("/General/SettingsVersion", SETTINGS_VERSION, "version of settings file"); SLCONFIG("/General/CacheVersion", CACHE_VERSION, "version of used cache"); SLCONFIG("/General/firstrun", true, "true if app is run first time"); @@ -107,7 +109,7 @@ void Settings::ConvertSettings(wxTranslationHelper* translationhelper, long sett //the dummy column hack was removed on win cfg().DeleteGroup(_T("/GUI/ColumnWidths/")); } - case 21: { + case 19: case 20: case 21: { if (translationhelper) { // add locale's language code to autojoin if (translationhelper->GetLocale()) { @@ -122,13 +124,7 @@ void Settings::ConvertSettings(wxTranslationHelper* translationhelper, long sett case 22: { ConvertLists(); } - case 23: { - DeleteServer(_T("Backup server")); - DeleteServer(_T("Backup server 1")); - DeleteServer(_T("Backup server 2")); - SetDefaultServerSettings(); - } - case 24: { + case 23: case 24: { SetDisableSpringVersionCheck(false); } case 25: { // language id before was stored by index, now its stored by the id @@ -140,14 +136,17 @@ void Settings::ConvertSettings(wxTranslationHelper* translationhelper, long sett case 27: { RemoveChannelJoin(_("main")); } - case 28: { - SetDefaultServerSettings(); - } - case 30: { + case 28: case 29: case 30: { #ifdef WIN32 // https://github.com/springlobby/springlobby/issues/385 cfg().Write(_T("/GUI/UseNotificationPopups"), true); #endif } + case 31: { + DeleteServer(_T("Backup server 1")); + DeleteServer(_T("Backup server 2")); + SetDefaultServerSettings(); + } + default: { } } @@ -241,10 +240,8 @@ bool Settings::ShouldAddDefaultServerSettings() //! @brief Restores default settings void Settings::SetDefaultServerSettings() { - SetServer(DEFSETT_DEFAULT_SERVER_NAME, DEFSETT_DEFAULT_SERVER_HOST, DEFSETT_DEFAULT_SERVER_PORT); - SetServer(_T( "Backup server 1" ), _T( "lobby1.springlobby.info" ), 8200); - SetServer(_T( "Backup server 2" ), _T( "lobby2.springlobby.info" ), 8200); - SetServer(_T( "Test server" ), _T( "lobby.springrts.com" ), 7000); + SetServer(DEFSETT_DEFAULT_SERVER_NAME, DEFSETT_DEFAULT_SERVER_HOST, DEFSETT_DEFAULT_SERVER_PORT, "0124dc0f4295b401a2d81ade3dc81b7a467eb9a70b0a4912b5e15fede735fe73"); + SetServer("Test server", "lobby.springrts.com", 7000, "bafee3142009baa105ade65b0f712ca5fcf30de8e91664a8825e0185a609277c"); SetDefaultServer(DEFSETT_DEFAULT_SERVER_NAME); } @@ -290,10 +287,12 @@ wxString Settings::GetServerHost(const wxString& server_name) //! @param server_name the server name/alias //! @param the host url address //! @param the port where the service is run -void Settings::SetServer(const wxString& server_name, const wxString& url, int port) +void Settings::SetServer(const wxString& server_name, const wxString& url, int port, const wxString& fingerprint) { cfg().Write(_T( "/Server/Servers/" ) + server_name + _T( "/Host" ), url); cfg().Write(_T( "/Server/Servers/" ) + server_name + _T( "/Port" ), port); + cfg().Write(_T( "/Server/Servers/" ) + server_name + _T( "/TLS" ), true); + cfg().Write(_T( "/Server/Servers/" ) + server_name + _T( "/Certificate" ), fingerprint); } //! @brief Deletes a server from the list. @@ -366,7 +365,7 @@ void Settings::SetServerAccountPass(const wxString& server_name, const wxString& //! @todo Implement bool Settings::GetServerAccountSavePass(const wxString& server_name) { - return cfg().Read(_T( "/Server/Servers/" ) + server_name + _T( "/savepass" ), (long int)false); + return cfg().Read(_T( "/Server/Servers/" ) + server_name + _T( "/savepass" ), (long int)DEFSETT_SAVE_PASSWORD); } @@ -1506,3 +1505,24 @@ unsigned int Settings::GetNotificationPopupDisplayTime() { return cfg().Read(_T("/GUI/NotificationPopupDisplayTime"), 5l); } + +bool Settings::IsServerTLS(const std::string& server_name) +{ + return cfg().Read(_T( "/Server/Servers/" ) + TowxString(server_name) + _T( "/TLS" ), true); +} + +void Settings::SetServerTLS(const std::string& server_name, bool enabled) +{ + cfg().Write(_T( "/Server/Servers/" ) + TowxString(server_name) + _T( "/TLS" ), enabled); +} + +std::string Settings::GetServerFingerprint(const std::string& server_name) +{ + return STD_STRING(cfg().Read(_T( "/Server/Servers/" ) + TowxString(server_name) + _T( "/Certificate" ), "")); +} + +void Settings::SetServerFingerprint(const std::string& server_name, const std::string& fingerprint) +{ + cfg().Write(_T( "/Server/Servers/" ) + TowxString(server_name) + _T( "/Certificate" ), TowxString(fingerprint)); +} + diff --git a/src/settings.h b/src/settings.h index 9ac11eb..3dcf13d 100644 --- a/src/settings.h +++ b/src/settings.h @@ -12,15 +12,12 @@ #include "useractions.h" #include "utils/sortutil.h" -const long CACHE_VERSION = 15; -const long SETTINGS_VERSION = 31; - const wxString DEFSETT_DEFAULT_SERVER_NAME = _T("Official server"); const wxString DEFSETT_DEFAULT_SERVER_HOST = _T("lobby.springrts.com"); const wxString BattlePostfix = _T("_battle"); const int DEFSETT_DEFAULT_SERVER_PORT = 8200; -const bool DEFSETT_SAVE_PASSWORD = false; +const bool DEFSETT_SAVE_PASSWORD = true; const unsigned int DEFSETT_SPRING_PORT = 8452; const long SET_MODE_EXPERT = 5000; @@ -172,10 +169,17 @@ public: wxArrayString GetServers(); bool ServerExists(const wxString& server_name); - void SetServer(const wxString& server_name, const wxString& url, int port); + void SetServer(const wxString& server_name, const wxString& url, int port, const wxString& fingerprint); void DeleteServer(const wxString& server_name); bool ShouldAddDefaultServerSettings(); + + bool IsServerTLS(const std::string& server_name); + void SetServerTLS(const std::string& server_name, bool enabled); + + std::string GetServerFingerprint(const std::string& server_name); + void SetServerFingerprint(const std::string& serve_name, const std::string& fingerprint); + /**@}*/ /* ================================================================ */ diff --git a/src/socket.cpp b/src/socket.cpp index ab541df..c4ffcb4 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -37,6 +37,13 @@ lsl/networking/socket.cpp #include <net/if.h> #endif +#ifdef SSL_SUPPORT +#include <openssl/bio.h> +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <openssl/x509.h> +#endif + #ifdef __WXMSW__ bool GetMac(std::vector<unsigned char>& mac) @@ -161,9 +168,147 @@ Socket::Socket(iNetClass& netclass) , m_net_class(netclass) , m_rate(-1) , m_sent(0) + +{ +#ifdef SSL_SUPPORT +m_starttls = false; +m_verified = false; +m_sslctx = nullptr; +m_ssl = nullptr; +#endif + +} + +#ifdef SSL_SUPPORT + +// http://roxlu.com/2014/042/using-openssl-with-memory-bios + +void Socket::StopTLS() +{ + m_starttls = false; + m_verified = false; + if (m_ssl != nullptr) { + SSL_free(m_ssl); + m_ssl = nullptr; + SSL_CTX_free(m_sslctx); + m_sslctx = nullptr; + } + ERR_free_strings(); + EVP_cleanup(); +} + +void Socket::DoSSLHandshake() { + const int ret = SSL_do_handshake(m_ssl); + wxLogDebug("SSL_do_handshake(): ret %d", ret); + if (ret < 0) { // fatal error + const int r = SSL_get_error(m_ssl, ret); + if (SSL_ERROR_WANT_READ == r) { + wxLogDebug("SSL_ERROR_WANT_READ"); + int pending = BIO_ctrl_pending(m_outbio); + if (pending > 0) { + wxLogDebug("SSL_do_handshake(): m_outbio pending == %d", pending); + char buf[4096]; + const int read = BIO_read(m_outbio, buf, sizeof(buf)); + if (read > 0) { + wxLogDebug("BIO_read() m_outbio: %d", read); + m_sock.Write(buf, read); + } + } + pending = BIO_ctrl_pending(m_inbio); + if (pending > 0) { + wxLogWarning("SSL_do_handshake(): m_inbio pending == %d", pending); + } + + } else { + wxLogError("SSL_get_error(): %d", r); + Disconnect(); + } + } else if (ret == 2) { //controlled shutdown + } // ret == 1 is successful +} + +void Socket::StartTLS(const std::string& fingerprint) +{ + wxLogMessage("Starting TLS..."); + m_excepted_fingerprint = fingerprint; + assert(!m_starttls); + m_starttls = true; + SSL_load_error_strings(); + SSL_library_init(); + ERR_load_BIO_strings(); + OpenSSL_add_all_algorithms(); + m_sslctx = SSL_CTX_new(SSLv23_client_method()); + SSL_CTX_set_options(m_sslctx, SSL_OP_NO_SSLv3); + m_ssl = SSL_new(m_sslctx); + SSL_set_connect_state(m_ssl); + m_inbio = BIO_new(BIO_s_mem()); + m_outbio = BIO_new(BIO_s_mem()); + + BIO_set_mem_eof_return(m_inbio, -1); + BIO_set_mem_eof_return(m_outbio, -1); + SSL_set_bio(m_ssl, m_inbio, m_outbio); + + DoSSLHandshake(); + +} + +bool Socket::VerifyCertificate() +{ + if (m_verified) { + return true; + } + + X509* cert = SSL_get_peer_certificate(m_ssl); + if (cert == nullptr) { + return false; + } + + const EVP_MD *fprint_type = EVP_sha256(); + unsigned char fprint[EVP_MAX_MD_SIZE]; + unsigned int fprint_size = 0; + + if (!X509_digest(cert, fprint_type, fprint, &fprint_size)) { + return false; + } + + std::string fingerprint; + char buf[4]; + for(size_t i=0; i<fprint_size; i++) { + snprintf(buf, sizeof(buf), "%02x", fprint[i]); + fingerprint += buf[0]; + fingerprint += buf[1]; + } + m_fingerprint = fingerprint; + wxLogMessage("Certificate fingerprint: %s", m_fingerprint.c_str()); + + const char* version = SSL_get_version(m_ssl); + wxLogMessage("Using %s", version); + + const char* name = SSL_get_cipher_name(m_ssl); + wxLogMessage("Using cipher %s", name); + + //FIXME: read from config and prompt when missmatch / doesn't exist + if (fingerprint != m_excepted_fingerprint) { + m_net_class.OnInvalidFingerprintReceived(fingerprint); + return false; + } + +/* // we prefer certificate pinnig + + long res = SSL_get_verify_result(ssl); + if(!(X509_V_OK == res)) { + } +*/ + + + X509_free(cert); + m_verified = true; + return true; } +#endif + //! @brief Destructor Socket::~Socket() @@ -198,6 +343,8 @@ void Socket::Connect(const wxString& addr, const int port) } InitSocket(m_sock); + + m_sock.Connect(wxaddr, false); m_sock.SetTimeout(40); } @@ -210,6 +357,11 @@ void Socket::SetTimeout(const int seconds) //! @brief Disconnect from remote host if connected. void Socket::Disconnect() { +#ifdef SSL_SUPPORT + if (m_starttls) { + StopTLS(); + } +#endif const bool wasconnected = m_sock.IsConnected(); m_buffer.clear(); m_sock.Close(); @@ -221,6 +373,7 @@ void Socket::Disconnect() //! @brief Send data over connection. bool Socket::Send(const std::string& data) { + wxLogDebug("Socket::Send"); m_buffer += (const char*)data.c_str(); int crop = m_buffer.length(); if (m_rate > 0) { @@ -229,14 +382,48 @@ bool Socket::Send(const std::string& data) crop = max; } std::string send = m_buffer.substr(0, crop); +#ifdef SSL_SUPPORT + if (m_starttls) { + int res = 0; + if(!SSL_is_init_finished(m_ssl)) { + DoSSLHandshake(); + } else { + if (!VerifyCertificate()) { + wxLogWarning("Couldn't verify certificate, closing connection"); + Disconnect(); + } + } + + if (send.length() > 0) { + const int ret = SSL_write(m_ssl, send.c_str(), send.length()); + if (ret > 0) { + res += ret; + } else if (ret == 0) { + wxLogDebug("SSL_read(); %d", ret); + } else { + wxLogWarning("SSL_read(); %d", ret); + } + } + if (BIO_ctrl_pending(m_outbio) > 0) { + char outbuf[4096]; + const int read = BIO_read(m_outbio, outbuf, sizeof(outbuf)); + assert(read > 0); + m_sock.Write(outbuf, read); + } + m_buffer.erase(0, res); + m_sent += res; + return true; + } //wxLogMessage( _T("send: %d sent: %d max: %d : buff: %d"), send.length() , m_sent, max, m_buffer.length() ); +#endif m_sock.Write(send.c_str(), send.length()); - if (!m_sock.Error()) { - wxUint32 sentdata = m_sock.LastCount(); - m_buffer.erase(0, sentdata); - m_sent += sentdata; + if (m_sock.Error()) { + return false; } - return !m_sock.Error(); + wxUint32 sentdata = m_sock.LastCount(); + m_buffer.erase(0, sentdata); + m_sent += sentdata; + return true; } @@ -282,20 +469,59 @@ wxString convert(char* buff, const int len) //! @brief Receive data from connection wxString Socket::Receive() { - wxString ret; - static const int chunk_size = 1500; + wxLogDebug("Socket::Receive"); + wxString res; + static const int chunk_size = 4096; char buf[chunk_size]; int readnum = 0; do { m_sock.Read(buf, chunk_size); readnum = m_sock.LastCount(); - if (readnum > 0) { - ret += convert(buf, readnum); +#ifdef SSL_SUPPORT + if (!m_starttls && (readnum == 0)) { + return res; } +#endif + wxLogDebug("Receive() %d", readnum); +#ifdef SSL_SUPPORT + if (m_starttls) { + if (readnum > 0) { + const int written = BIO_write(m_inbio, buf, readnum); + if (written <= 0) { + wxLogDebug("BIO_write(): %d", written); + } + } + if(!SSL_is_init_finished(m_ssl)) { + DoSSLHandshake(); + } else { + if (!VerifyCertificate()) { + wxLogWarning("Couldn't verify certificate, closing connection"); + Disconnect(); + return wxEmptyString; + } + int ret = 0; + do { + ret = SSL_read(m_ssl, buf, chunk_size); + if (ret >= 0) { + const std::string str(buf, ret); + res += convert(buf, ret); + } else if (ret == 0) { + wxLogWarning("SSL_read(); %d", ret); + } else { + wxLogDebug("SSL_read(): %d", ret); + } + } while(ret > 0); + } + } else { +#endif + res += convert(buf, readnum); +#ifdef SSL_SUPPORT + } +#endif } while (readnum > 0); - return ret; + return res; } //! @brief Get curent socket state diff --git a/src/socket.h b/src/socket.h index fa13e95..8a2a6c2 100644 --- a/src/socket.h +++ b/src/socket.h @@ -23,6 +23,15 @@ lsl/networking/socket.h class iNetClass; class wxCriticalSection; +#ifdef SSL_SUPPORT +#include <openssl/ssl.h> + +//win compile hack +#ifdef GetUserName +#undef GetUserName +#endif +#endif + enum SockState { SS_Closed, SS_Connecting, @@ -72,7 +81,10 @@ public: void Update(int mselapsed); void SetTimeout(const int seconds); - +#ifdef SSL_SUPPORT + void StartTLS(const std::string& fingerprint); + bool IsTLS() { return m_starttls; } +#endif private: void OnSocketEvent(wxSocketEvent& event); void InitSocket(wxSocketClient& socket); @@ -87,6 +99,19 @@ private: int m_rate; int m_sent; std::string m_buffer; +#ifdef SSL_SUPPORT + void StopTLS(); + void DoSSLHandshake(); + bool VerifyCertificate(); + bool m_verified; + bool m_starttls; + SSL_CTX *m_sslctx; + SSL *m_ssl; + BIO *m_inbio; + BIO *m_outbio; + std::string m_fingerprint; + std::string m_excepted_fingerprint; +#endif DECLARE_EVENT_TABLE(); }; diff --git a/src/tasserver.cpp b/src/tasserver.cpp index 5e7fd8d..23209ce 100644 --- a/src/tasserver.cpp +++ b/src/tasserver.cpp @@ -35,7 +35,6 @@ lsl/networking/tasserver.cpp #include "utils/version.h" #include <lslutils/misc.h> - SLCONFIG("/Server/ExitMessage", "Using http://springlobby.info/", "Message which is send when leaving server"); // times in milliseconds @@ -399,7 +398,6 @@ void TASServer::RequestChannels() void TASServer::AcceptAgreement() { SendCmd("CONFIRMAGREEMENT"); - Login(); } @@ -532,12 +530,21 @@ void TASServer::ExecuteCommand(const std::string& cmd, const std::string& inpara UserBattleStatus bstatus; if (cmd == "TASSERVER") { - m_ser_ver = GetIntParam(params); - const std::string supported_spring_version = GetWordParam(params); - m_nat_helper_port = (unsigned long)GetIntParam(params); - const bool lanmode = GetBoolParam(params); - m_server_lanmode = lanmode; - m_se->OnConnected(m_serverinfo.description, "", (m_ser_ver > 0), supported_spring_version, lanmode); +#ifdef SSL_SUPPORT + if (!m_sock->IsTLS() && sett().IsServerTLS(GetServerName()) ) { + SendCmd("STARTTLS", ""); + m_sock->StartTLS(sett().GetServerFingerprint(GetServerName())); + } else { +#endif + m_ser_ver = GetIntParam(params); + const std::string supported_spring_version = GetWordParam(params); + m_nat_helper_port = (unsigned long)GetIntParam(params); + const bool lanmode = GetBoolParam(params); + m_server_lanmode = lanmode; + m_se->OnConnected(m_serverinfo.description, "", (m_ser_ver > 0), supported_spring_version, lanmode); +#ifdef SSL_SUPPORT + } +#endif } else if (cmd == "ACCEPTED") { SetUsername(params); m_se->OnLogin(); @@ -1733,7 +1740,6 @@ void TASServer::RemoveBot(int battleid, User& bot) } IBattle& battle = GetBattle(battleid); - ASSERT_LOGIC(&bot != 0, "Bot does not exist."); if (!(battle.IsFounderMe() || (bot.BattleStatus().owner == GetMe().GetNick()))) { DoActionBattle(battleid, "thinks the bot " + bot.GetNick() + " should be removed."); @@ -2024,3 +2030,10 @@ bool TASServer::IsCurrentBattle(int battle_id) } return true; } + +void TASServer::OnInvalidFingerprintReceived(const std::string& fingerprint) +{ + const std::string expected_fingerprint = sett().GetServerFingerprint(GetServerName()); + m_se->OnInvalidFingerprintReceived(fingerprint, expected_fingerprint); +} + diff --git a/src/tasserver.h b/src/tasserver.h index 0848ee8..07f3d73 100644 --- a/src/tasserver.h +++ b/src/tasserver.h @@ -147,6 +147,7 @@ private: void OnDisconnected(wxSocketError err) override; void OnDataReceived() override; void OnError(const std::string& err) override; + void OnInvalidFingerprintReceived(const std::string& fingerprint) override; void UDPPing(); /// used for nat travelsal /// generic udp "ping" function diff --git a/tools/mxe_create_builddir.sh b/tools/mxe_create_builddir.sh index e01746f..adf1b6a 100755 --- a/tools/mxe_create_builddir.sh +++ b/tools/mxe_create_builddir.sh @@ -18,7 +18,7 @@ git reset --hard $COMMIT ( echo 'JOBS := 2' echo 'MXE_TARGETS := i686-w64-mingw32.static' - echo 'LOCAL_PKG_LIST := boost curl wxwidgets' + echo 'LOCAL_PKG_LIST := openssl boost curl wxwidgets' echo '.DEFAULT local-pkg-list:' echo 'local-pkg-list: $(LOCAL_PKG_LIST)' ) > settings.mk -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/springlobby.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

