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

Reply via email to