[springlobby] 01/05: New upstream version 0.257+dfsg

Markus Koschany apo at moszumanska.debian.org
Sun Oct 1 18:37:58 UTC 2017


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 <apo at debian.org>
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



More information about the Pkg-games-commits mailing list