From 0cbfd8bdb5fbf091521831a6070cef8f92090378 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Fri, 6 Feb 2009 09:50:47 +0100 Subject: [PATCH] MP cleanup Expand the message union to provide member functions that return pointers into the message buffer. --- src/MultiPlayer/multiplaymgr.cxx | 170 +++++++++++++++++++++---------- src/MultiPlayer/multiplaymgr.hxx | 10 +- 2 files changed, 120 insertions(+), 60 deletions(-) diff --git a/src/MultiPlayer/multiplaymgr.cxx b/src/MultiPlayer/multiplaymgr.cxx index ee44918eb..855969238 100644 --- a/src/MultiPlayer/multiplaymgr.cxx +++ b/src/MultiPlayer/multiplaymgr.cxx @@ -33,6 +33,7 @@ #include #include +#include #include // isNaN #include @@ -46,7 +47,7 @@ #include "multiplaymgr.hxx" #include "mpmessages.hxx" -using std::cerr; +using namespace std; #define MAX_PACKET_SIZE 1200 #define MAX_TEXT_SIZE 128 @@ -447,6 +448,78 @@ FGMultiplayMgr::Close (void) // Description: Sends the position data for the local position. // ////////////////////////////////////////////////////////////////////// + +/** + * The buffer that holds a multi-player message, suitably aligned. + */ +union FGMultiplayMgr::MsgBuf +{ + MsgBuf() + { + memset(&Msg, 0, sizeof(Msg)); + } + + T_MsgHdr* msgHdr() + { + return reinterpret_cast(Msg); + } + + const T_MsgHdr* msgHdr() const + { + return reinterpret_cast(Msg); + } + + T_PositionMsg* posMsg() + { + return reinterpret_cast(Msg + sizeof(T_MsgHdr)); + } + + const T_PositionMsg* posMsg() const + { + return reinterpret_cast(Msg + sizeof(T_MsgHdr)); + } + + xdr_data_t* properties() + { + return reinterpret_cast(Msg + sizeof(T_MsgHdr) + + sizeof(T_PositionMsg)); + } + + const xdr_data_t* properties() const + { + return reinterpret_cast(Msg + sizeof(T_MsgHdr) + + sizeof(T_PositionMsg)); + } + /** + * The end of the properties buffer. + */ + xdr_data_t* propsEnd() + { + return reinterpret_cast(Msg + MAX_PACKET_SIZE); + }; + + const xdr_data_t* propsEnd() const + { + return reinterpret_cast(Msg + MAX_PACKET_SIZE); + }; + /** + * The end of properties actually in the buffer. This assumes that + * the message header is valid. + */ + xdr_data_t* propsRecvdEnd() + { + return reinterpret_cast(Msg + msgHdr()->MsgLen); + } + + const xdr_data_t* propsRecvdEnd() const + { + return reinterpret_cast(Msg + msgHdr()->MsgLen); + } + + xdr_data2_t double_val; + char Msg[MAX_PACKET_SIZE]; +}; + void FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) { @@ -457,42 +530,34 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) return; } - T_PositionMsg PosMsg; + MsgBuf msgBuf; + T_PositionMsg* PosMsg = msgBuf.posMsg(); - memset(&PosMsg, 0, sizeof(PosMsg)); - strncpy(PosMsg.Model, fgGetString("/sim/model/path"), MAX_MODEL_NAME_LEN); - PosMsg.Model[MAX_MODEL_NAME_LEN - 1] = '\0'; + strncpy(PosMsg->Model, fgGetString("/sim/model/path"), MAX_MODEL_NAME_LEN); + PosMsg->Model[MAX_MODEL_NAME_LEN - 1] = '\0'; - PosMsg.time = XDR_encode_double (motionInfo.time); - PosMsg.lag = XDR_encode_double (motionInfo.lag); + PosMsg->time = XDR_encode_double (motionInfo.time); + PosMsg->lag = XDR_encode_double (motionInfo.lag); for (unsigned i = 0 ; i < 3; ++i) - PosMsg.position[i] = XDR_encode_double (motionInfo.position(i)); + PosMsg->position[i] = XDR_encode_double (motionInfo.position(i)); SGVec3f angleAxis; motionInfo.orientation.getAngleAxis(angleAxis); for (unsigned i = 0 ; i < 3; ++i) - PosMsg.orientation[i] = XDR_encode_float (angleAxis(i)); + PosMsg->orientation[i] = XDR_encode_float (angleAxis(i)); for (unsigned i = 0 ; i < 3; ++i) - PosMsg.linearVel[i] = XDR_encode_float (motionInfo.linearVel(i)); + PosMsg->linearVel[i] = XDR_encode_float (motionInfo.linearVel(i)); for (unsigned i = 0 ; i < 3; ++i) - PosMsg.angularVel[i] = XDR_encode_float (motionInfo.angularVel(i)); + PosMsg->angularVel[i] = XDR_encode_float (motionInfo.angularVel(i)); for (unsigned i = 0 ; i < 3; ++i) - PosMsg.linearAccel[i] = XDR_encode_float (motionInfo.linearAccel(i)); + PosMsg->linearAccel[i] = XDR_encode_float (motionInfo.linearAccel(i)); for (unsigned i = 0 ; i < 3; ++i) - PosMsg.angularAccel[i] = XDR_encode_float (motionInfo.angularAccel(i)); - // ensure alignment of message buffer - union { - xdr_data2_t double_val; - char Msg[MAX_PACKET_SIZE]; - } msgBuf; - memcpy(msgBuf.Msg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg)); + PosMsg->angularAccel[i] = XDR_encode_float (motionInfo.angularAccel(i)); - xdr_data_t* ptr = reinterpret_cast(msgBuf.Msg + sizeof(T_MsgHdr) - + sizeof(T_PositionMsg)); + xdr_data_t* ptr = msgBuf.properties(); std::vector::const_iterator it; it = motionInfo.properties.begin(); //cout << "OUTPUT PROPERTIES\n"; - xdr_data_t* msgEnd = reinterpret_cast(msgBuf.Msg - + MAX_PACKET_SIZE); + xdr_data_t* msgEnd = msgBuf.propsEnd(); while (it != motionInfo.properties.end() && ptr + 2 < msgEnd) { // First element is the ID. Write it out when we know we have room for @@ -583,15 +648,12 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) ++it; } escape: - - T_MsgHdr MsgHdr; unsigned msgLen = reinterpret_cast(ptr) - msgBuf.Msg; - FillMsgHdr(&MsgHdr, POS_DATA_ID, msgLen); - memcpy(msgBuf.Msg, &MsgHdr, sizeof(T_MsgHdr)); - + FillMsgHdr(msgBuf.msgHdr(), POS_DATA_ID, msgLen); mSocket->sendto(msgBuf.Msg, msgLen, 0, &mServer); SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::SendMyPosition"); } // FGMultiplayMgr::SendMyPosition() + ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// @@ -657,11 +719,7 @@ FGMultiplayMgr::Update(void) ////////////////////////////////////////////////// int bytes; do { - // ensure alignment - union { - xdr_data2_t doubleVal; - char Msg[MAX_PACKET_SIZE]; - } msgBuf; + MsgBuf msgBuf; ////////////////////////////////////////////////// // Although the recv call asks for // MAX_PACKET_SIZE of data, the number of bytes @@ -687,7 +745,7 @@ FGMultiplayMgr::Update(void) ////////////////////////////////////////////////// // Read header ////////////////////////////////////////////////// - T_MsgHdr* MsgHdr = reinterpret_cast(msgBuf.Msg); + T_MsgHdr* MsgHdr = msgBuf.msgHdr(); MsgHdr->Magic = XDR_decode_uint32 (MsgHdr->Magic); MsgHdr->Version = XDR_decode_uint32 (MsgHdr->Version); MsgHdr->MsgId = XDR_decode_uint32 (MsgHdr->MsgId); @@ -714,10 +772,10 @@ FGMultiplayMgr::Update(void) ////////////////////////////////////////////////// switch (MsgHdr->MsgId) { case CHAT_MSG_ID: - ProcessChatMsg(msgBuf.Msg, SenderAddress); + ProcessChatMsg(msgBuf, SenderAddress); break; case POS_DATA_ID: - ProcessPosMsg(msgBuf.Msg, SenderAddress, bytes, stamp); + ProcessPosMsg(msgBuf, SenderAddress, stamp); break; case UNUSABLE_POS_DATA_ID: case OLD_OLD_POS_DATA_ID: @@ -751,17 +809,16 @@ FGMultiplayMgr::Update(void) // ////////////////////////////////////////////////////////////////////// void -FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, - unsigned len, long stamp) +FGMultiplayMgr::ProcessPosMsg(const FGMultiplayMgr::MsgBuf& Msg, + const netAddress& SenderAddress, long stamp) { - const T_MsgHdr* MsgHdr = reinterpret_cast(Msg); + const T_MsgHdr* MsgHdr = Msg.msgHdr(); if (MsgHdr->MsgLen < sizeof(T_MsgHdr) + sizeof(T_PositionMsg)) { SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " << "Position message received with insufficient data" ); return; } - const T_PositionMsg* PosMsg - = reinterpret_cast(Msg + sizeof(T_MsgHdr)); + const T_PositionMsg* PosMsg = Msg.posMsg(); FGExternalMotionData motionInfo; motionInfo.time = XDR_decode_double(PosMsg->time); motionInfo.lag = XDR_decode_double(PosMsg->lag); @@ -782,7 +839,7 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, //cout << "INPUT MESSAGE\n"; - const xdr_data_t* xdr = (xdr_data_t*)(Msg + sizeof(T_MsgHdr) + sizeof(T_PositionMsg)); + // There was a bug in 1.9.0 and before: T_PositionMsg was 196 bytes // on 32 bit architectures and 200 bytes on 64 bit, and this // structure is put directly on the wire. By looking at the padding, @@ -798,15 +855,14 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, // There is a chance that we could be fooled by garbage in the // padding looking like a valid property, so verifyProperties() is // strict about the validity of the property values. + const xdr_data_t* xdr = Msg.properties(); if (PosMsg->pad != 0) { - if (verifyProperties(&PosMsg->pad, - reinterpret_cast(Msg + len))) + if (verifyProperties(&PosMsg->pad, Msg.propsRecvdEnd())) xdr = &PosMsg->pad; - else if (!verifyProperties(xdr, - reinterpret_cast(Msg + len))) + else if (!verifyProperties(xdr, Msg.propsRecvdEnd())) goto noprops; } - while ((char*)xdr < Msg + len) { + while (xdr < Msg.propsRecvdEnd()) { FGPropertyData* pData = new FGPropertyData; SGPropertyNode::Type type = SGPropertyNode::UNSPECIFIED; @@ -903,25 +959,29 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, // ////////////////////////////////////////////////////////////////////// void -FGMultiplayMgr::ProcessChatMsg(const char *Msg, netAddress& SenderAddress) +FGMultiplayMgr::ProcessChatMsg(const MsgBuf& Msg, + const netAddress& SenderAddress) { - T_MsgHdr* MsgHdr = (T_MsgHdr *)Msg; + const T_MsgHdr* MsgHdr = Msg.msgHdr(); if (MsgHdr->MsgLen < sizeof(T_MsgHdr) + 1) { SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " << "Chat message received with insufficient data" ); return; } - char *MsgBuf = new char[MsgHdr->MsgLen - sizeof(T_MsgHdr)]; - strncpy(MsgBuf, ((T_ChatMsg *)(Msg + sizeof(T_MsgHdr)))->Text, + char *chatStr = new char[MsgHdr->MsgLen - sizeof(T_MsgHdr)]; + strncpy(chatStr, + (reinterpret_cast(Msg.Msg + sizeof(T_MsgHdr))) + ->Text, MsgHdr->MsgLen - sizeof(T_MsgHdr)); - MsgBuf[MsgHdr->MsgLen - sizeof(T_MsgHdr) - 1] = '\0'; + chatStr[MsgHdr->MsgLen - sizeof(T_MsgHdr) - 1] = '\0'; - T_ChatMsg* ChatMsg = (T_ChatMsg *)(Msg + sizeof(T_MsgHdr)); + const T_ChatMsg* ChatMsg + = reinterpret_cast(Msg.Msg + sizeof(T_MsgHdr)); SG_LOG (SG_NETWORK, SG_ALERT, "Chat [" << MsgHdr->Callsign << "]" - << " " << MsgBuf); + << " " << chatStr); - delete [] MsgBuf; + delete [] chatStr; } // FGMultiplayMgr::ProcessChatMsg () ////////////////////////////////////////////////////////////////////// diff --git a/src/MultiPlayer/multiplaymgr.hxx b/src/MultiPlayer/multiplaymgr.hxx index 2cca356c5..ab110ed3b 100644 --- a/src/MultiPlayer/multiplaymgr.hxx +++ b/src/MultiPlayer/multiplaymgr.hxx @@ -72,18 +72,18 @@ public: // transmitter void SendMyPosition(const FGExternalMotionData& motionInfo); void SendTextMessage(const string &sMsgText); - void FillMsgHdr(T_MsgHdr *MsgHdr, int iMsgId, unsigned _len = 0u); - // receiver - void ProcessPosMsg(const char *Msg, netAddress & SenderAddress, - unsigned len, long stamp); - void ProcessChatMsg(const char *Msg, netAddress & SenderAddress); void Update(void); private: + union MsgBuf; FGAIMultiplayer* addMultiplayer(const std::string& callsign, const std::string& modelName); FGAIMultiplayer* getMultiplayer(const std::string& callsign); + void FillMsgHdr(T_MsgHdr *MsgHdr, int iMsgId, unsigned _len = 0u); + void ProcessPosMsg(const MsgBuf& Msg, const netAddress& SenderAddress, + long stamp); + void ProcessChatMsg(const MsgBuf& Msg, const netAddress& SenderAddress); /// maps from the callsign string to the FGAIMultiplayer typedef std::map > MultiPlayerMap; -- 2.39.5