Browse Source

Survive client<->server ABI mismatch

Vadim Markovtsev 9 years ago
parent
commit
eac5aab396
7 changed files with 27 additions and 13 deletions
  1. 9 3
      client/Client.cpp
  2. 1 1
      lib/Connection.cpp
  3. 9 2
      lib/Connection.h
  4. 1 1
      lib/NetPacks.h
  5. 4 3
      lib/NetPacksBase.h
  6. 1 1
      lib/NetPacksLib.cpp
  7. 2 2
      server/CGameHandler.cpp

+ 9 - 3
client/Client.cpp

@@ -653,20 +653,26 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
 
 
 void CClient::handlePack( CPack * pack )
 void CClient::handlePack( CPack * pack )
 {
 {
+	if (pack == nullptr)
+	{
+		logNetwork->errorStream() << "Dropping nullptr CPack! You should check whether client and server ABI matches.";
+		return;
+	}
 	CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
 	CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
 	if(apply)
 	if(apply)
 	{
 	{
 		boost::unique_lock<boost::recursive_mutex> guiLock(*LOCPLINT->pim);
 		boost::unique_lock<boost::recursive_mutex> guiLock(*LOCPLINT->pim);
-		apply->applyOnClBefore(this,pack);
+		apply->applyOnClBefore(this, pack);
 		logNetwork->traceStream() << "\tMade first apply on cl";
 		logNetwork->traceStream() << "\tMade first apply on cl";
 		gs->apply(pack);
 		gs->apply(pack);
 		logNetwork->traceStream() << "\tApplied on gs";
 		logNetwork->traceStream() << "\tApplied on gs";
-		apply->applyOnClAfter(this,pack);
+		apply->applyOnClAfter(this, pack);
 		logNetwork->traceStream() << "\tMade second apply on cl";
 		logNetwork->traceStream() << "\tMade second apply on cl";
 	}
 	}
 	else
 	else
 	{
 	{
-		logNetwork->errorStream() << "Message cannot be applied, cannot find applier! TypeID " << typeList.getTypeID(pack);
+		logNetwork->errorStream() << "Message cannot be applied, cannot find applier! type "
+                              << pack->type << " - " << typeList.getTypeInfo(pack)->name();
 	}
 	}
 	delete pack;
 	delete pack;
 }
 }

+ 1 - 1
lib/Connection.cpp

@@ -225,7 +225,7 @@ CPack * CConnection::retreivePack()
 	boost::unique_lock<boost::mutex> lock(*rmx);
 	boost::unique_lock<boost::mutex> lock(*rmx);
 	logNetwork->traceStream() << "Listening... ";
 	logNetwork->traceStream() << "Listening... ";
 	iser >> ret;
 	iser >> ret;
-	logNetwork->traceStream() << "\treceived server message of type " << typeid(*ret).name() << ", data: " << ret;
+	logNetwork->traceStream() << "\treceived server message of type " << (ret? typeid(*ret).name() : "nullptr") << ", data: " << ret;
 	return ret;
 	return ret;
 }
 }
 
 

+ 9 - 2
lib/Connection.h

@@ -1107,7 +1107,7 @@ public:
 	};
 	};
 
 
 	bool saving;
 	bool saving;
-	std::map<ui16,CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
+	std::map<ui16, CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
 	si32 fileVersion;
 	si32 fileVersion;
 	bool reverseEndianess; //if source has different endianness than us, we reverse bytes
 	bool reverseEndianess; //if source has different endianness than us, we reverse bytes
 
 
@@ -1308,7 +1308,14 @@ public:
 		}
 		}
 		else
 		else
 		{
 		{
-			auto typeInfo = loaders[tid]->loadPtr(*this,&data, pid);
+			auto loader = loaders[tid];
+			if (loader == nullptr)
+			{
+				logGlobal->errorStream() << "loadPointerHlp " << tid << " " << pid << " - no loader exists";
+				data = nullptr;
+				return;
+			}
+			auto typeInfo = loader->loadPtr(*this, &data, pid);
 			data = reinterpret_cast<T>(typeList.castRaw((void*)data, typeInfo, &typeid(typename boost::remove_const<typename boost::remove_pointer<T>::type>::type)));
 			data = reinterpret_cast<T>(typeList.castRaw((void*)data, typeInfo, &typeid(typename boost::remove_const<typename boost::remove_pointer<T>::type>::type)));
 		}
 		}
 	}
 	}

+ 1 - 1
lib/NetPacks.h

@@ -2188,7 +2188,7 @@ struct CenterView : public CPackForClient//515
 
 
 struct CPackForSelectionScreen : public CPack
 struct CPackForSelectionScreen : public CPack
 {
 {
-	void apply(CSelectionScreen *selScreen){}; //that functions are implemented in CPreGame.cpp
+	void apply(CSelectionScreen *selScreen) {} // implemented in CPreGame.cpp
 };
 };
 
 
 class CPregamePackToPropagate  : public CPackForSelectionScreen
 class CPregamePackToPropagate  : public CPackForSelectionScreen

+ 4 - 3
lib/NetPacksBase.h

@@ -29,12 +29,13 @@ struct DLL_LINKAGE CPack
 {
 {
 	ui16 type;
 	ui16 type;
 
 
-	CPack(){};
-	virtual ~CPack(){};
-	ui16 getType() const{return type;}
+	CPack() {};
+	virtual ~CPack() {};
+	ui16 getType() const { return type; }
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
 		logNetwork->errorStream() << "CPack serialized... this should not happen!";
 		logNetwork->errorStream() << "CPack serialized... this should not happen!";
+		assert(false && "CPack serialized");
 	}
 	}
 	void applyGs(CGameState *gs) { }
 	void applyGs(CGameState *gs) { }
 	virtual std::string toString() const { return boost::str(boost::format("{CPack: type '%d'}") % type); }
 	virtual std::string toString() const { return boost::str(boost::format("{CPack: type '%d'}") % type); }

+ 1 - 1
lib/NetPacksLib.cpp

@@ -34,7 +34,7 @@
 
 
 std::ostream & operator<<(std::ostream & out, const CPack * pack)
 std::ostream & operator<<(std::ostream & out, const CPack * pack)
 {
 {
-	return out << pack->toString();
+	return out << (pack? pack->toString() : "<nullptr>");
 }
 }
 
 
 DLL_LINKAGE void SetResource::applyGs( CGameState *gs )
 DLL_LINKAGE void SetResource::applyGs( CGameState *gs )

+ 2 - 2
server/CGameHandler.cpp

@@ -965,9 +965,9 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
 			}
 			}
 			else if(apply)
 			else if(apply)
 			{
 			{
-				const bool result = apply->applyOnGH(this,&c,pack, player);
+				const bool result = apply->applyOnGH(this, &c, pack, player);
 				if(result)
 				if(result)
-					logGlobal->trace("Message successfully applied!");
+					logGlobal->traceStream() << "Message " << typeid(*pack).name() << " successfully applied!";
 				else
 				else
 					complain((boost::format("Got false in applying %s... that request must have been fishy!")
 					complain((boost::format("Got false in applying %s... that request must have been fishy!")
 						% typeid(*pack).name()).str());
 						% typeid(*pack).name()).str());