Merge branch 'maint' into next
This commit is contained in:
commit
8a756eee54
4 changed files with 154 additions and 27 deletions
|
@ -108,6 +108,12 @@ struct T_PositionMsg {
|
||||||
// angular acceleration wrt the earth centered frame measured in
|
// angular acceleration wrt the earth centered frame measured in
|
||||||
// the earth centered frame
|
// the earth centered frame
|
||||||
xdr_data_t angularAccel[3];
|
xdr_data_t angularAccel[3];
|
||||||
|
// Padding. The alignment is 8 bytes on x86_64 because there are
|
||||||
|
// 8-byte types in the message, so the size should be explicitly
|
||||||
|
// rounded out to a multiple of 8. Of course, it's a bad idea to
|
||||||
|
// put a C struct directly on the wire, but that's a fight for
|
||||||
|
// another day...
|
||||||
|
xdr_data_t pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FGPropertyData {
|
struct FGPropertyData {
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <osg/Math> // isNaN
|
||||||
#include <plib/netSocket.h>
|
#include <plib/netSocket.h>
|
||||||
|
|
||||||
#include <simgear/misc/stdint.hxx>
|
#include <simgear/misc/stdint.hxx>
|
||||||
|
@ -58,7 +60,7 @@ const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID;
|
||||||
// This should be extendable dynamically for every specific aircraft ...
|
// This should be extendable dynamically for every specific aircraft ...
|
||||||
// For now only that static list
|
// For now only that static list
|
||||||
FGMultiplayMgr::IdPropertyList
|
FGMultiplayMgr::IdPropertyList
|
||||||
FGMultiplayMgr::sIdPropertyList[] = {
|
const FGMultiplayMgr::sIdPropertyList[] = {
|
||||||
{100, "surface-positions/left-aileron-pos-norm", SGPropertyNode::FLOAT},
|
{100, "surface-positions/left-aileron-pos-norm", SGPropertyNode::FLOAT},
|
||||||
{101, "surface-positions/right-aileron-pos-norm", SGPropertyNode::FLOAT},
|
{101, "surface-positions/right-aileron-pos-norm", SGPropertyNode::FLOAT},
|
||||||
{102, "surface-positions/elevator-pos-norm", SGPropertyNode::FLOAT},
|
{102, "surface-positions/elevator-pos-norm", SGPropertyNode::FLOAT},
|
||||||
|
@ -222,11 +224,115 @@ FGMultiplayMgr::sIdPropertyList[] = {
|
||||||
{10317, "sim/multiplay/generic/int[17]", SGPropertyNode::INT},
|
{10317, "sim/multiplay/generic/int[17]", SGPropertyNode::INT},
|
||||||
{10318, "sim/multiplay/generic/int[18]", SGPropertyNode::INT},
|
{10318, "sim/multiplay/generic/int[18]", SGPropertyNode::INT},
|
||||||
{10319, "sim/multiplay/generic/int[19]", SGPropertyNode::INT},
|
{10319, "sim/multiplay/generic/int[19]", SGPropertyNode::INT},
|
||||||
|
|
||||||
/// termination
|
|
||||||
{0, 0, SGPropertyNode::UNSPECIFIED}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unsigned
|
||||||
|
FGMultiplayMgr::numProperties = (sizeof(FGMultiplayMgr::sIdPropertyList)
|
||||||
|
/ sizeof(FGMultiplayMgr::sIdPropertyList[0]));
|
||||||
|
|
||||||
|
// Look up a property ID using binary search.
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct ComparePropertyId
|
||||||
|
{
|
||||||
|
bool operator()(const FGMultiplayMgr::IdPropertyList& lhs,
|
||||||
|
const FGMultiplayMgr::IdPropertyList& rhs)
|
||||||
|
{
|
||||||
|
return lhs.id < rhs.id;
|
||||||
|
}
|
||||||
|
bool operator()(const FGMultiplayMgr::IdPropertyList& lhs,
|
||||||
|
unsigned id)
|
||||||
|
{
|
||||||
|
return lhs.id < id;
|
||||||
|
}
|
||||||
|
bool operator()(unsigned id,
|
||||||
|
const FGMultiplayMgr::IdPropertyList& rhs)
|
||||||
|
{
|
||||||
|
return id < rhs.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
const FGMultiplayMgr::IdPropertyList* FGMultiplayMgr::findProperty(unsigned id)
|
||||||
|
{
|
||||||
|
std::pair<const IdPropertyList*, const IdPropertyList*> result
|
||||||
|
= std::equal_range(sIdPropertyList, sIdPropertyList + numProperties, id,
|
||||||
|
ComparePropertyId());
|
||||||
|
if (result.first == result.second) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return result.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool verifyProperties(const xdr_data_t* data, const xdr_data_t* end)
|
||||||
|
{
|
||||||
|
const xdr_data_t* xdr = data;
|
||||||
|
while (xdr < end) {
|
||||||
|
unsigned id = XDR_decode_uint32(*xdr);
|
||||||
|
const FGMultiplayMgr::IdPropertyList* plist
|
||||||
|
= FGMultiplayMgr::findProperty(id);
|
||||||
|
|
||||||
|
if (plist) {
|
||||||
|
xdr++;
|
||||||
|
// How we decode the remainder of the property depends on the type
|
||||||
|
switch (plist->type) {
|
||||||
|
case SGPropertyNode::INT:
|
||||||
|
case SGPropertyNode::BOOL:
|
||||||
|
case SGPropertyNode::LONG:
|
||||||
|
xdr++;
|
||||||
|
break;
|
||||||
|
case SGPropertyNode::FLOAT:
|
||||||
|
case SGPropertyNode::DOUBLE:
|
||||||
|
{
|
||||||
|
float val = XDR_decode_float(*xdr);
|
||||||
|
if (osg::isNaN(val))
|
||||||
|
return false;
|
||||||
|
xdr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::STRING:
|
||||||
|
case SGPropertyNode::UNSPECIFIED:
|
||||||
|
{
|
||||||
|
// String is complicated. It consists of
|
||||||
|
// The length of the string
|
||||||
|
// The string itself
|
||||||
|
// Padding to the nearest 4-bytes.
|
||||||
|
// XXX Yes, each byte is padded out to a word! Too late
|
||||||
|
// to change...
|
||||||
|
uint32_t length = XDR_decode_uint32(*xdr);
|
||||||
|
xdr++;
|
||||||
|
if ((length > 0) && (length < MAX_TEXT_SIZE)) {
|
||||||
|
xdr += length;
|
||||||
|
// Now handle the padding
|
||||||
|
while ((length % 4) != 0)
|
||||||
|
{
|
||||||
|
xdr++;
|
||||||
|
length++;
|
||||||
|
//cout << "0";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The string appears to be invalid; bail.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// cerr << "Unknown Prop type " << id << " " << type << "\n";
|
||||||
|
xdr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// give up; this is a malformed property list.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// MultiplayMgr constructor
|
// MultiplayMgr constructor
|
||||||
|
@ -355,6 +461,8 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
T_PositionMsg PosMsg;
|
T_PositionMsg PosMsg;
|
||||||
|
|
||||||
|
memset(&PosMsg, 0, sizeof(PosMsg));
|
||||||
strncpy(PosMsg.Model, fgGetString("/sim/model/path"), MAX_MODEL_NAME_LEN);
|
strncpy(PosMsg.Model, fgGetString("/sim/model/path"), MAX_MODEL_NAME_LEN);
|
||||||
PosMsg.Model[MAX_MODEL_NAME_LEN - 1] = '\0';
|
PosMsg.Model[MAX_MODEL_NAME_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
@ -677,6 +785,29 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress,
|
||||||
//cout << "INPUT MESSAGE\n";
|
//cout << "INPUT MESSAGE\n";
|
||||||
xdr_data_t* xdr = (xdr_data_t*)
|
xdr_data_t* xdr = (xdr_data_t*)
|
||||||
(Msg + sizeof(T_MsgHdr) + sizeof(T_PositionMsg));
|
(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,
|
||||||
|
// we can sort through the mess, mostly:
|
||||||
|
// If padding is 0 (which is not a valid property type), then the
|
||||||
|
// message was produced by a new client or an old 64 bit client that
|
||||||
|
// happened to have 0 on the stack;
|
||||||
|
// Else if the property list starting with the padding word is
|
||||||
|
// well-formed, then the client is probably an old 32 bit client and
|
||||||
|
// we'll go with that;
|
||||||
|
// Else it is an old 64-bit client and properties start after the
|
||||||
|
// padding.
|
||||||
|
// 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.
|
||||||
|
if (PosMsg->pad != 0) {
|
||||||
|
if (verifyProperties(&PosMsg->pad,
|
||||||
|
reinterpret_cast<const xdr_data_t*>(Msg + len)))
|
||||||
|
xdr = &PosMsg->pad;
|
||||||
|
else if (!verifyProperties(xdr,
|
||||||
|
reinterpret_cast<const xdr_data_t*>(Msg + len)))
|
||||||
|
goto noprops;
|
||||||
|
}
|
||||||
while ((char*)xdr < Msg + len) {
|
while ((char*)xdr < Msg + len) {
|
||||||
FGPropertyData* pData = new FGPropertyData;
|
FGPropertyData* pData = new FGPropertyData;
|
||||||
SGPropertyNode::Type type = SGPropertyNode::UNSPECIFIED;
|
SGPropertyNode::Type type = SGPropertyNode::UNSPECIFIED;
|
||||||
|
@ -687,21 +818,11 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress,
|
||||||
xdr++;
|
xdr++;
|
||||||
|
|
||||||
// Check the ID actually exists and get the type
|
// Check the ID actually exists and get the type
|
||||||
unsigned i = 0;
|
const IdPropertyList* plist = findProperty(pData->id);
|
||||||
bool found = false;
|
|
||||||
while (FGMultiplayMgr::sIdPropertyList[i].name)
|
|
||||||
{
|
|
||||||
if (sIdPropertyList[i].id == pData->id)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
pData->type = sIdPropertyList[i].type;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
if (plist)
|
||||||
}
|
|
||||||
|
|
||||||
if (found == true)
|
|
||||||
{
|
{
|
||||||
|
pData->type = plist->type;
|
||||||
// How we decode the remainder of the property depends on the type
|
// How we decode the remainder of the property depends on the type
|
||||||
switch (pData->type) {
|
switch (pData->type) {
|
||||||
case SGPropertyNode::INT:
|
case SGPropertyNode::INT:
|
||||||
|
@ -772,10 +893,11 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We failed to find the property. We'll try the next packet immediately.
|
// We failed to find the property. We'll try the next packet immediately.
|
||||||
//cout << " Unknown\n";
|
SG_LOG(SG_NETWORK, SG_WARN, "FGMultiplayMgr::ProcessPosMsg - "
|
||||||
|
<< "found unknown property id" << pData->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
noprops:
|
||||||
FGAIMultiplayer* mp = getMultiplayer(MsgHdr->Callsign);
|
FGAIMultiplayer* mp = getMultiplayer(MsgHdr->Callsign);
|
||||||
if (!mp)
|
if (!mp)
|
||||||
mp = addMultiplayer(MsgHdr->Callsign, PosMsg->Model);
|
mp = addMultiplayer(MsgHdr->Callsign, PosMsg->Model);
|
||||||
|
@ -854,11 +976,8 @@ FGMultiplayMgr::addMultiplayer(const std::string& callsign,
|
||||||
aiMgr->attach(mp);
|
aiMgr->attach(mp);
|
||||||
|
|
||||||
/// FIXME: that must follow the attach ATM ...
|
/// FIXME: that must follow the attach ATM ...
|
||||||
unsigned i = 0;
|
for (unsigned i = 0; i < numProperties; ++i)
|
||||||
while (sIdPropertyList[i].name) {
|
|
||||||
mp->addPropertyId(sIdPropertyList[i].id, sIdPropertyList[i].name);
|
mp->addPropertyId(sIdPropertyList[i].id, sIdPropertyList[i].name);
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mp;
|
return mp;
|
||||||
|
|
|
@ -60,7 +60,10 @@ public:
|
||||||
const char* name;
|
const char* name;
|
||||||
SGPropertyNode::Type type;
|
SGPropertyNode::Type type;
|
||||||
};
|
};
|
||||||
static IdPropertyList sIdPropertyList[];
|
static const IdPropertyList sIdPropertyList[];
|
||||||
|
static const unsigned numProperties;
|
||||||
|
|
||||||
|
static const IdPropertyList* findProperty(unsigned id);
|
||||||
|
|
||||||
FGMultiplayMgr();
|
FGMultiplayMgr();
|
||||||
~FGMultiplayMgr();
|
~FGMultiplayMgr();
|
||||||
|
|
|
@ -101,13 +101,12 @@ bool FGMultiplay::open() {
|
||||||
SGPropertyNode* root = globals->get_props();
|
SGPropertyNode* root = globals->get_props();
|
||||||
|
|
||||||
/// Build up the id to property map
|
/// Build up the id to property map
|
||||||
unsigned i = 0;
|
|
||||||
while (FGMultiplayMgr::sIdPropertyList[i].name) {
|
for (unsigned i = 0; i < FGMultiplayMgr::numProperties; ++i) {
|
||||||
const char* name = FGMultiplayMgr::sIdPropertyList[i].name;
|
const char* name = FGMultiplayMgr::sIdPropertyList[i].name;
|
||||||
SGPropertyNode* pNode = root->getNode(name);
|
SGPropertyNode* pNode = root->getNode(name);
|
||||||
if (pNode)
|
if (pNode)
|
||||||
mPropertyMap[FGMultiplayMgr::sIdPropertyList[i].id] = pNode;
|
mPropertyMap[FGMultiplayMgr::sIdPropertyList[i].id] = pNode;
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_enabled();
|
return is_enabled();
|
||||||
|
|
Loading…
Add table
Reference in a new issue