X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMultiPlayer%2Fmultiplaymgr.cxx;h=fe1f4c399912b3df7c7efb20f2a82f39ddf3aae5;hb=ad13e4f3b42c53410cb695d2dd0083af77addb2e;hp=acd483111d1128c363be7c72046d717dbedb5945;hpb=cd4b05909db86ba823cb2dd5b4769dab5b69568c;p=flightgear.git diff --git a/src/MultiPlayer/multiplaymgr.cxx b/src/MultiPlayer/multiplaymgr.cxx index acd483111..fe1f4c399 100644 --- a/src/MultiPlayer/multiplaymgr.cxx +++ b/src/MultiPlayer/multiplaymgr.cxx @@ -32,6 +32,9 @@ #endif #include +#include +#include +#include // isNaN #include #include @@ -44,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 @@ -57,176 +60,280 @@ const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID; // A static map of protocol property id values to property paths, // This should be extendable dynamically for every specific aircraft ... // For now only that static list -FGMultiplayMgr::IdPropertyList +const FGMultiplayMgr::IdPropertyList FGMultiplayMgr::sIdPropertyList[] = { - {100, "surface-positions/left-aileron-pos-norm", SGPropertyNode::FLOAT}, - {101, "surface-positions/right-aileron-pos-norm", SGPropertyNode::FLOAT}, - {102, "surface-positions/elevator-pos-norm", SGPropertyNode::FLOAT}, - {103, "surface-positions/rudder-pos-norm", SGPropertyNode::FLOAT}, - {104, "surface-positions/flap-pos-norm", SGPropertyNode::FLOAT}, - {105, "surface-positions/speedbrake-pos-norm", SGPropertyNode::FLOAT}, - {106, "gear/tailhook/position-norm", SGPropertyNode::FLOAT}, - {107, "gear/launchbar/position-norm", SGPropertyNode::FLOAT}, - {108, "gear/launchbar/state", SGPropertyNode::STRING}, - {109, "gear/launchbar/holdback-position-norm", SGPropertyNode::FLOAT}, - {110, "canopy/position-norm", SGPropertyNode::FLOAT}, - {111, "surface-positions/wing-pos-norm", SGPropertyNode::FLOAT}, - {112, "surface-positions/wing-fold-pos-norm", SGPropertyNode::FLOAT}, - - {200, "gear/gear[0]/compression-norm", SGPropertyNode::FLOAT}, - {201, "gear/gear[0]/position-norm", SGPropertyNode::FLOAT}, - {210, "gear/gear[1]/compression-norm", SGPropertyNode::FLOAT}, - {211, "gear/gear[1]/position-norm", SGPropertyNode::FLOAT}, - {220, "gear/gear[2]/compression-norm", SGPropertyNode::FLOAT}, - {221, "gear/gear[2]/position-norm", SGPropertyNode::FLOAT}, - {230, "gear/gear[3]/compression-norm", SGPropertyNode::FLOAT}, - {231, "gear/gear[3]/position-norm", SGPropertyNode::FLOAT}, - {240, "gear/gear[4]/compression-norm", SGPropertyNode::FLOAT}, - {241, "gear/gear[4]/position-norm", SGPropertyNode::FLOAT}, - - {300, "engines/engine[0]/n1", SGPropertyNode::FLOAT}, - {301, "engines/engine[0]/n2", SGPropertyNode::FLOAT}, - {302, "engines/engine[0]/rpm", SGPropertyNode::FLOAT}, - {310, "engines/engine[1]/n1", SGPropertyNode::FLOAT}, - {311, "engines/engine[1]/n2", SGPropertyNode::FLOAT}, - {312, "engines/engine[1]/rpm", SGPropertyNode::FLOAT}, - {320, "engines/engine[2]/n1", SGPropertyNode::FLOAT}, - {321, "engines/engine[2]/n2", SGPropertyNode::FLOAT}, - {322, "engines/engine[2]/rpm", SGPropertyNode::FLOAT}, - {330, "engines/engine[3]/n1", SGPropertyNode::FLOAT}, - {331, "engines/engine[3]/n2", SGPropertyNode::FLOAT}, - {332, "engines/engine[3]/rpm", SGPropertyNode::FLOAT}, - {340, "engines/engine[4]/n1", SGPropertyNode::FLOAT}, - {341, "engines/engine[4]/n2", SGPropertyNode::FLOAT}, - {342, "engines/engine[4]/rpm", SGPropertyNode::FLOAT}, - {350, "engines/engine[5]/n1", SGPropertyNode::FLOAT}, - {351, "engines/engine[5]/n2", SGPropertyNode::FLOAT}, - {352, "engines/engine[5]/rpm", SGPropertyNode::FLOAT}, - {360, "engines/engine[6]/n1", SGPropertyNode::FLOAT}, - {361, "engines/engine[6]/n2", SGPropertyNode::FLOAT}, - {362, "engines/engine[6]/rpm", SGPropertyNode::FLOAT}, - {370, "engines/engine[7]/n1", SGPropertyNode::FLOAT}, - {371, "engines/engine[7]/n2", SGPropertyNode::FLOAT}, - {372, "engines/engine[7]/rpm", SGPropertyNode::FLOAT}, - {380, "engines/engine[8]/n1", SGPropertyNode::FLOAT}, - {381, "engines/engine[8]/n2", SGPropertyNode::FLOAT}, - {382, "engines/engine[8]/rpm", SGPropertyNode::FLOAT}, - {390, "engines/engine[9]/n1", SGPropertyNode::FLOAT}, - {391, "engines/engine[9]/n2", SGPropertyNode::FLOAT}, - {392, "engines/engine[9]/rpm", SGPropertyNode::FLOAT}, - - {800, "rotors/main/rpm", SGPropertyNode::FLOAT}, - {801, "rotors/tail/rpm", SGPropertyNode::FLOAT}, - {810, "rotors/main/blade[0]/position-deg", SGPropertyNode::FLOAT}, - {811, "rotors/main/blade[1]/position-deg", SGPropertyNode::FLOAT}, - {812, "rotors/main/blade[2]/position-deg", SGPropertyNode::FLOAT}, - {813, "rotors/main/blade[3]/position-deg", SGPropertyNode::FLOAT}, - {820, "rotors/main/blade[0]/flap-deg", SGPropertyNode::FLOAT}, - {821, "rotors/main/blade[1]/flap-deg", SGPropertyNode::FLOAT}, - {822, "rotors/main/blade[2]/flap-deg", SGPropertyNode::FLOAT}, - {823, "rotors/main/blade[3]/flap-deg", SGPropertyNode::FLOAT}, - {830, "rotors/tail/blade[0]/position-deg", SGPropertyNode::FLOAT}, - {831, "rotors/tail/blade[1]/position-deg", SGPropertyNode::FLOAT}, - - {900, "sim/hitches/aerotow/tow/length", SGPropertyNode::FLOAT}, - {901, "sim/hitches/aerotow/tow/elastic-constant", SGPropertyNode::FLOAT}, - {902, "sim/hitches/aerotow/tow/weight-per-m-kg-m", SGPropertyNode::FLOAT}, - {903, "sim/hitches/aerotow/tow/dist", SGPropertyNode::FLOAT}, - {904, "sim/hitches/aerotow/tow/connected-to-property-node", SGPropertyNode::BOOL}, - {905, "sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign", SGPropertyNode::STRING}, - {906, "sim/hitches/aerotow/tow/brake-force", SGPropertyNode::FLOAT}, - {907, "sim/hitches/aerotow/tow/end-force-x", SGPropertyNode::FLOAT}, - {908, "sim/hitches/aerotow/tow/end-force-y", SGPropertyNode::FLOAT}, - {909, "sim/hitches/aerotow/tow/end-force-z", SGPropertyNode::FLOAT}, - {930, "sim/hitches/aerotow/is-slave", SGPropertyNode::BOOL}, - {931, "sim/hitches/aerotow/speed-in-tow-direction", SGPropertyNode::FLOAT}, - {932, "sim/hitches/aerotow/open", SGPropertyNode::BOOL}, - {933, "sim/hitches/aerotow/local-pos-x", SGPropertyNode::FLOAT}, - {934, "sim/hitches/aerotow/local-pos-y", SGPropertyNode::FLOAT}, - {935, "sim/hitches/aerotow/local-pos-z", SGPropertyNode::FLOAT}, - - {1001, "controls/flight/slats", SGPropertyNode::FLOAT}, - {1002, "controls/flight/speedbrake", SGPropertyNode::FLOAT}, - {1003, "controls/flight/spoilers", SGPropertyNode::FLOAT}, - {1004, "controls/gear/gear-down", SGPropertyNode::FLOAT}, - {1005, "controls/lighting/nav-lights", SGPropertyNode::FLOAT}, - {1006, "controls/armament/station[0]/jettison-all", SGPropertyNode::BOOL}, - - {1100, "sim/model/variant", SGPropertyNode::INT}, - {1101, "sim/model/livery/file", SGPropertyNode::STRING}, - - {1200, "environment/wildfire/data", SGPropertyNode::STRING}, - - {10001, "sim/multiplay/transmission-freq-hz", SGPropertyNode::STRING}, - {10002, "sim/multiplay/chat", SGPropertyNode::STRING}, - - {10100, "sim/multiplay/generic/string[0]", SGPropertyNode::STRING}, - {10101, "sim/multiplay/generic/string[1]", SGPropertyNode::STRING}, - {10102, "sim/multiplay/generic/string[2]", SGPropertyNode::STRING}, - {10103, "sim/multiplay/generic/string[3]", SGPropertyNode::STRING}, - {10104, "sim/multiplay/generic/string[4]", SGPropertyNode::STRING}, - {10105, "sim/multiplay/generic/string[5]", SGPropertyNode::STRING}, - {10106, "sim/multiplay/generic/string[6]", SGPropertyNode::STRING}, - {10107, "sim/multiplay/generic/string[7]", SGPropertyNode::STRING}, - {10108, "sim/multiplay/generic/string[8]", SGPropertyNode::STRING}, - {10109, "sim/multiplay/generic/string[9]", SGPropertyNode::STRING}, - {10110, "sim/multiplay/generic/string[10]", SGPropertyNode::STRING}, - {10111, "sim/multiplay/generic/string[11]", SGPropertyNode::STRING}, - {10112, "sim/multiplay/generic/string[12]", SGPropertyNode::STRING}, - {10113, "sim/multiplay/generic/string[13]", SGPropertyNode::STRING}, - {10114, "sim/multiplay/generic/string[14]", SGPropertyNode::STRING}, - {10115, "sim/multiplay/generic/string[15]", SGPropertyNode::STRING}, - {10116, "sim/multiplay/generic/string[16]", SGPropertyNode::STRING}, - {10117, "sim/multiplay/generic/string[17]", SGPropertyNode::STRING}, - {10118, "sim/multiplay/generic/string[18]", SGPropertyNode::STRING}, - {10119, "sim/multiplay/generic/string[19]", SGPropertyNode::STRING}, - - {10200, "sim/multiplay/generic/float[0]", SGPropertyNode::FLOAT}, - {10201, "sim/multiplay/generic/float[1]", SGPropertyNode::FLOAT}, - {10202, "sim/multiplay/generic/float[2]", SGPropertyNode::FLOAT}, - {10203, "sim/multiplay/generic/float[3]", SGPropertyNode::FLOAT}, - {10204, "sim/multiplay/generic/float[4]", SGPropertyNode::FLOAT}, - {10205, "sim/multiplay/generic/float[5]", SGPropertyNode::FLOAT}, - {10206, "sim/multiplay/generic/float[6]", SGPropertyNode::FLOAT}, - {10207, "sim/multiplay/generic/float[7]", SGPropertyNode::FLOAT}, - {10208, "sim/multiplay/generic/float[8]", SGPropertyNode::FLOAT}, - {10209, "sim/multiplay/generic/float[9]", SGPropertyNode::FLOAT}, - {10210, "sim/multiplay/generic/float[10]", SGPropertyNode::FLOAT}, - {10211, "sim/multiplay/generic/float[11]", SGPropertyNode::FLOAT}, - {10212, "sim/multiplay/generic/float[12]", SGPropertyNode::FLOAT}, - {10213, "sim/multiplay/generic/float[13]", SGPropertyNode::FLOAT}, - {10214, "sim/multiplay/generic/float[14]", SGPropertyNode::FLOAT}, - {10215, "sim/multiplay/generic/float[15]", SGPropertyNode::FLOAT}, - {10216, "sim/multiplay/generic/float[16]", SGPropertyNode::FLOAT}, - {10217, "sim/multiplay/generic/float[17]", SGPropertyNode::FLOAT}, - {10218, "sim/multiplay/generic/float[18]", SGPropertyNode::FLOAT}, - {10219, "sim/multiplay/generic/float[19]", SGPropertyNode::FLOAT}, - - {10300, "sim/multiplay/generic/int[0]", SGPropertyNode::INT}, - {10301, "sim/multiplay/generic/int[1]", SGPropertyNode::INT}, - {10302, "sim/multiplay/generic/int[2]", SGPropertyNode::INT}, - {10303, "sim/multiplay/generic/int[3]", SGPropertyNode::INT}, - {10304, "sim/multiplay/generic/int[4]", SGPropertyNode::INT}, - {10305, "sim/multiplay/generic/int[5]", SGPropertyNode::INT}, - {10306, "sim/multiplay/generic/int[6]", SGPropertyNode::INT}, - {10307, "sim/multiplay/generic/int[7]", SGPropertyNode::INT}, - {10308, "sim/multiplay/generic/int[8]", SGPropertyNode::INT}, - {10309, "sim/multiplay/generic/int[9]", SGPropertyNode::INT}, - {10310, "sim/multiplay/generic/int[10]", SGPropertyNode::INT}, - {10311, "sim/multiplay/generic/int[11]", SGPropertyNode::INT}, - {10312, "sim/multiplay/generic/int[12]", SGPropertyNode::INT}, - {10313, "sim/multiplay/generic/int[13]", SGPropertyNode::INT}, - {10314, "sim/multiplay/generic/int[14]", SGPropertyNode::INT}, - {10315, "sim/multiplay/generic/int[15]", SGPropertyNode::INT}, - {10316, "sim/multiplay/generic/int[16]", SGPropertyNode::INT}, - {10317, "sim/multiplay/generic/int[17]", SGPropertyNode::INT}, - {10318, "sim/multiplay/generic/int[18]", SGPropertyNode::INT}, - {10319, "sim/multiplay/generic/int[19]", SGPropertyNode::INT}, - - /// termination - {0, 0, SGPropertyNode::UNSPECIFIED} + {100, "surface-positions/left-aileron-pos-norm", simgear::props::FLOAT}, + {101, "surface-positions/right-aileron-pos-norm", simgear::props::FLOAT}, + {102, "surface-positions/elevator-pos-norm", simgear::props::FLOAT}, + {103, "surface-positions/rudder-pos-norm", simgear::props::FLOAT}, + {104, "surface-positions/flap-pos-norm", simgear::props::FLOAT}, + {105, "surface-positions/speedbrake-pos-norm", simgear::props::FLOAT}, + {106, "gear/tailhook/position-norm", simgear::props::FLOAT}, + {107, "gear/launchbar/position-norm", simgear::props::FLOAT}, + {108, "gear/launchbar/state", simgear::props::STRING}, + {109, "gear/launchbar/holdback-position-norm", simgear::props::FLOAT}, + {110, "canopy/position-norm", simgear::props::FLOAT}, + {111, "surface-positions/wing-pos-norm", simgear::props::FLOAT}, + {112, "surface-positions/wing-fold-pos-norm", simgear::props::FLOAT}, + + {200, "gear/gear[0]/compression-norm", simgear::props::FLOAT}, + {201, "gear/gear[0]/position-norm", simgear::props::FLOAT}, + {210, "gear/gear[1]/compression-norm", simgear::props::FLOAT}, + {211, "gear/gear[1]/position-norm", simgear::props::FLOAT}, + {220, "gear/gear[2]/compression-norm", simgear::props::FLOAT}, + {221, "gear/gear[2]/position-norm", simgear::props::FLOAT}, + {230, "gear/gear[3]/compression-norm", simgear::props::FLOAT}, + {231, "gear/gear[3]/position-norm", simgear::props::FLOAT}, + {240, "gear/gear[4]/compression-norm", simgear::props::FLOAT}, + {241, "gear/gear[4]/position-norm", simgear::props::FLOAT}, + + {300, "engines/engine[0]/n1", simgear::props::FLOAT}, + {301, "engines/engine[0]/n2", simgear::props::FLOAT}, + {302, "engines/engine[0]/rpm", simgear::props::FLOAT}, + {310, "engines/engine[1]/n1", simgear::props::FLOAT}, + {311, "engines/engine[1]/n2", simgear::props::FLOAT}, + {312, "engines/engine[1]/rpm", simgear::props::FLOAT}, + {320, "engines/engine[2]/n1", simgear::props::FLOAT}, + {321, "engines/engine[2]/n2", simgear::props::FLOAT}, + {322, "engines/engine[2]/rpm", simgear::props::FLOAT}, + {330, "engines/engine[3]/n1", simgear::props::FLOAT}, + {331, "engines/engine[3]/n2", simgear::props::FLOAT}, + {332, "engines/engine[3]/rpm", simgear::props::FLOAT}, + {340, "engines/engine[4]/n1", simgear::props::FLOAT}, + {341, "engines/engine[4]/n2", simgear::props::FLOAT}, + {342, "engines/engine[4]/rpm", simgear::props::FLOAT}, + {350, "engines/engine[5]/n1", simgear::props::FLOAT}, + {351, "engines/engine[5]/n2", simgear::props::FLOAT}, + {352, "engines/engine[5]/rpm", simgear::props::FLOAT}, + {360, "engines/engine[6]/n1", simgear::props::FLOAT}, + {361, "engines/engine[6]/n2", simgear::props::FLOAT}, + {362, "engines/engine[6]/rpm", simgear::props::FLOAT}, + {370, "engines/engine[7]/n1", simgear::props::FLOAT}, + {371, "engines/engine[7]/n2", simgear::props::FLOAT}, + {372, "engines/engine[7]/rpm", simgear::props::FLOAT}, + {380, "engines/engine[8]/n1", simgear::props::FLOAT}, + {381, "engines/engine[8]/n2", simgear::props::FLOAT}, + {382, "engines/engine[8]/rpm", simgear::props::FLOAT}, + {390, "engines/engine[9]/n1", simgear::props::FLOAT}, + {391, "engines/engine[9]/n2", simgear::props::FLOAT}, + {392, "engines/engine[9]/rpm", simgear::props::FLOAT}, + + {800, "rotors/main/rpm", simgear::props::FLOAT}, + {801, "rotors/tail/rpm", simgear::props::FLOAT}, + {810, "rotors/main/blade[0]/position-deg", simgear::props::FLOAT}, + {811, "rotors/main/blade[1]/position-deg", simgear::props::FLOAT}, + {812, "rotors/main/blade[2]/position-deg", simgear::props::FLOAT}, + {813, "rotors/main/blade[3]/position-deg", simgear::props::FLOAT}, + {820, "rotors/main/blade[0]/flap-deg", simgear::props::FLOAT}, + {821, "rotors/main/blade[1]/flap-deg", simgear::props::FLOAT}, + {822, "rotors/main/blade[2]/flap-deg", simgear::props::FLOAT}, + {823, "rotors/main/blade[3]/flap-deg", simgear::props::FLOAT}, + {830, "rotors/tail/blade[0]/position-deg", simgear::props::FLOAT}, + {831, "rotors/tail/blade[1]/position-deg", simgear::props::FLOAT}, + + {900, "sim/hitches/aerotow/tow/length", simgear::props::FLOAT}, + {901, "sim/hitches/aerotow/tow/elastic-constant", simgear::props::FLOAT}, + {902, "sim/hitches/aerotow/tow/weight-per-m-kg-m", simgear::props::FLOAT}, + {903, "sim/hitches/aerotow/tow/dist", simgear::props::FLOAT}, + {904, "sim/hitches/aerotow/tow/connected-to-property-node", simgear::props::BOOL}, + {905, "sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign", simgear::props::STRING}, + {906, "sim/hitches/aerotow/tow/brake-force", simgear::props::FLOAT}, + {907, "sim/hitches/aerotow/tow/end-force-x", simgear::props::FLOAT}, + {908, "sim/hitches/aerotow/tow/end-force-y", simgear::props::FLOAT}, + {909, "sim/hitches/aerotow/tow/end-force-z", simgear::props::FLOAT}, + {930, "sim/hitches/aerotow/is-slave", simgear::props::BOOL}, + {931, "sim/hitches/aerotow/speed-in-tow-direction", simgear::props::FLOAT}, + {932, "sim/hitches/aerotow/open", simgear::props::BOOL}, + {933, "sim/hitches/aerotow/local-pos-x", simgear::props::FLOAT}, + {934, "sim/hitches/aerotow/local-pos-y", simgear::props::FLOAT}, + {935, "sim/hitches/aerotow/local-pos-z", simgear::props::FLOAT}, + + {1001, "controls/flight/slats", simgear::props::FLOAT}, + {1002, "controls/flight/speedbrake", simgear::props::FLOAT}, + {1003, "controls/flight/spoilers", simgear::props::FLOAT}, + {1004, "controls/gear/gear-down", simgear::props::FLOAT}, + {1005, "controls/lighting/nav-lights", simgear::props::FLOAT}, + {1006, "controls/armament/station[0]/jettison-all", simgear::props::BOOL}, + + {1100, "sim/model/variant", simgear::props::INT}, + {1101, "sim/model/livery/file", simgear::props::STRING}, + + {1200, "environment/wildfire/data", simgear::props::STRING}, + + {10001, "sim/multiplay/transmission-freq-hz", simgear::props::STRING}, + {10002, "sim/multiplay/chat", simgear::props::STRING}, + + {10100, "sim/multiplay/generic/string[0]", simgear::props::STRING}, + {10101, "sim/multiplay/generic/string[1]", simgear::props::STRING}, + {10102, "sim/multiplay/generic/string[2]", simgear::props::STRING}, + {10103, "sim/multiplay/generic/string[3]", simgear::props::STRING}, + {10104, "sim/multiplay/generic/string[4]", simgear::props::STRING}, + {10105, "sim/multiplay/generic/string[5]", simgear::props::STRING}, + {10106, "sim/multiplay/generic/string[6]", simgear::props::STRING}, + {10107, "sim/multiplay/generic/string[7]", simgear::props::STRING}, + {10108, "sim/multiplay/generic/string[8]", simgear::props::STRING}, + {10109, "sim/multiplay/generic/string[9]", simgear::props::STRING}, + {10110, "sim/multiplay/generic/string[10]", simgear::props::STRING}, + {10111, "sim/multiplay/generic/string[11]", simgear::props::STRING}, + {10112, "sim/multiplay/generic/string[12]", simgear::props::STRING}, + {10113, "sim/multiplay/generic/string[13]", simgear::props::STRING}, + {10114, "sim/multiplay/generic/string[14]", simgear::props::STRING}, + {10115, "sim/multiplay/generic/string[15]", simgear::props::STRING}, + {10116, "sim/multiplay/generic/string[16]", simgear::props::STRING}, + {10117, "sim/multiplay/generic/string[17]", simgear::props::STRING}, + {10118, "sim/multiplay/generic/string[18]", simgear::props::STRING}, + {10119, "sim/multiplay/generic/string[19]", simgear::props::STRING}, + + {10200, "sim/multiplay/generic/float[0]", simgear::props::FLOAT}, + {10201, "sim/multiplay/generic/float[1]", simgear::props::FLOAT}, + {10202, "sim/multiplay/generic/float[2]", simgear::props::FLOAT}, + {10203, "sim/multiplay/generic/float[3]", simgear::props::FLOAT}, + {10204, "sim/multiplay/generic/float[4]", simgear::props::FLOAT}, + {10205, "sim/multiplay/generic/float[5]", simgear::props::FLOAT}, + {10206, "sim/multiplay/generic/float[6]", simgear::props::FLOAT}, + {10207, "sim/multiplay/generic/float[7]", simgear::props::FLOAT}, + {10208, "sim/multiplay/generic/float[8]", simgear::props::FLOAT}, + {10209, "sim/multiplay/generic/float[9]", simgear::props::FLOAT}, + {10210, "sim/multiplay/generic/float[10]", simgear::props::FLOAT}, + {10211, "sim/multiplay/generic/float[11]", simgear::props::FLOAT}, + {10212, "sim/multiplay/generic/float[12]", simgear::props::FLOAT}, + {10213, "sim/multiplay/generic/float[13]", simgear::props::FLOAT}, + {10214, "sim/multiplay/generic/float[14]", simgear::props::FLOAT}, + {10215, "sim/multiplay/generic/float[15]", simgear::props::FLOAT}, + {10216, "sim/multiplay/generic/float[16]", simgear::props::FLOAT}, + {10217, "sim/multiplay/generic/float[17]", simgear::props::FLOAT}, + {10218, "sim/multiplay/generic/float[18]", simgear::props::FLOAT}, + {10219, "sim/multiplay/generic/float[19]", simgear::props::FLOAT}, + + {10300, "sim/multiplay/generic/int[0]", simgear::props::INT}, + {10301, "sim/multiplay/generic/int[1]", simgear::props::INT}, + {10302, "sim/multiplay/generic/int[2]", simgear::props::INT}, + {10303, "sim/multiplay/generic/int[3]", simgear::props::INT}, + {10304, "sim/multiplay/generic/int[4]", simgear::props::INT}, + {10305, "sim/multiplay/generic/int[5]", simgear::props::INT}, + {10306, "sim/multiplay/generic/int[6]", simgear::props::INT}, + {10307, "sim/multiplay/generic/int[7]", simgear::props::INT}, + {10308, "sim/multiplay/generic/int[8]", simgear::props::INT}, + {10309, "sim/multiplay/generic/int[9]", simgear::props::INT}, + {10310, "sim/multiplay/generic/int[10]", simgear::props::INT}, + {10311, "sim/multiplay/generic/int[11]", simgear::props::INT}, + {10312, "sim/multiplay/generic/int[12]", simgear::props::INT}, + {10313, "sim/multiplay/generic/int[13]", simgear::props::INT}, + {10314, "sim/multiplay/generic/int[14]", simgear::props::INT}, + {10315, "sim/multiplay/generic/int[15]", simgear::props::INT}, + {10316, "sim/multiplay/generic/int[16]", simgear::props::INT}, + {10317, "sim/multiplay/generic/int[17]", simgear::props::INT}, + {10318, "sim/multiplay/generic/int[18]", simgear::props::INT}, + {10319, "sim/multiplay/generic/int[19]", simgear::props::INT} }; +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 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) + { + using namespace simgear; + 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 props::INT: + case props::BOOL: + case props::LONG: + xdr++; + break; + case props::FLOAT: + case props::DOUBLE: + { + float val = XDR_decode_float(*xdr); + if (osg::isNaN(val)) + return false; + xdr++; + break; + } + case props::STRING: + case props::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++; + // Old versions truncated the string but left the length + // unadjusted. + if (length > MAX_TEXT_SIZE) + length = MAX_TEXT_SIZE; + xdr += length; + // Now handle the padding + while ((length % 4) != 0) + { + xdr++; + length++; + //cout << "0"; + } + } + 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 @@ -278,7 +385,7 @@ FGMultiplayMgr::init (void) mServer.set(txAddress.c_str(), txPort); if (strncmp (mServer.getHost(), "0.0.0.0", 8) == 0) { mHaveServer = false; - SG_LOG(SG_NETWORK, SG_ALERT, + SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr - could not resolve '" << txAddress << "', Multiplayermode disabled"); } else { @@ -288,7 +395,7 @@ FGMultiplayMgr::init (void) rxPort = txPort; } if (rxPort <= 0) { - SG_LOG(SG_NETWORK, SG_ALERT, + SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr - No receiver port, Multiplayermode disabled"); return (false); } @@ -303,14 +410,14 @@ FGMultiplayMgr::init (void) // A memory leak was reported here by valgrind mSocket = new netSocket(); if (!mSocket->open(false)) { - SG_LOG( SG_NETWORK, SG_ALERT, + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::init - Failed to create data socket" ); return false; } mSocket->setBlocking(false); if (mSocket->bind(rxAddress.c_str(), rxPort) != 0) { perror("bind"); - SG_LOG( SG_NETWORK, SG_ALERT, + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::Open - Failed to bind receive socket" ); return false; } @@ -344,71 +451,138 @@ 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) { if ((! mInitialised) || (! mHaveServer)) return; if (! mHaveServer) { - SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::SendMyPosition - no server"); + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::SendMyPosition - no server"); return; } - T_PositionMsg PosMsg; - strncpy(PosMsg.Model, fgGetString("/sim/model/path"), MAX_MODEL_NAME_LEN); - PosMsg.Model[MAX_MODEL_NAME_LEN - 1] = '\0'; + MsgBuf msgBuf; + T_PositionMsg* PosMsg = msgBuf.posMsg(); + + 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)); - - char Msg[MAX_PACKET_SIZE]; - memcpy(Msg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg)); + PosMsg->angularAccel[i] = XDR_encode_float (motionInfo.angularAccel(i)); - char* ptr = 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"; - while (it != motionInfo.properties.end() - && ptr + 2 * sizeof(xdr_data_t) < (Msg + MAX_PACKET_SIZE)) { - - // First elements is the ID - xdr_data_t xdr = XDR_encode_uint32((*it)->id); - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + 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 + // the whole property. + xdr_data_t id = XDR_encode_uint32((*it)->id); // The actual data representation depends on the type switch ((*it)->type) { - case SGPropertyNode::INT: - case SGPropertyNode::BOOL: - case SGPropertyNode::LONG: - xdr = XDR_encode_uint32((*it)->int_value); - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + case simgear::props::INT: + case simgear::props::BOOL: + case simgear::props::LONG: + *ptr++ = id; + *ptr++ = XDR_encode_uint32((*it)->int_value); //cout << "Prop:" << (*it)->id << " " << (*it)->type << " "<< (*it)->int_value << "\n"; break; - case SGPropertyNode::FLOAT: - case SGPropertyNode::DOUBLE: - xdr = XDR_encode_float((*it)->float_value);; - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + case simgear::props::FLOAT: + case simgear::props::DOUBLE: + *ptr++ = id; + *ptr++ = XDR_encode_float((*it)->float_value); //cout << "Prop:" << (*it)->id << " " << (*it)->type << " "<< (*it)->float_value << "\n"; break; - case SGPropertyNode::STRING: - case SGPropertyNode::UNSPECIFIED: + case simgear::props::STRING: + case simgear::props::UNSPECIFIED: { // String is complicated. It consists of // The length of the string @@ -421,26 +595,24 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) // Add the length ////cout << "String length: " << strlen(lcharptr) << "\n"; uint32_t len = strlen(lcharptr); + if (len > MAX_TEXT_SIZE) + len = MAX_TEXT_SIZE; // XXX This should not be using 4 bytes per character! - if (ptr + (1 + len + (4 - len % 4)) * sizeof (xdr_data_t) - >= (Msg + MAX_PACKET_SIZE)) + // If there's not enough room for this property, drop it + // on the floor. + if (ptr + 2 + ((len + 3) & ~3) > msgEnd) goto escape; //cout << "String length unint32: " << len << "\n"; - xdr = XDR_encode_uint32(len); - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); - + *ptr++ = id; + *ptr++ = XDR_encode_uint32(len); if (len != 0) { - // Now the text itself // XXX This should not be using 4 bytes per character! int lcount = 0; while ((*lcharptr != '\0') && (lcount < MAX_TEXT_SIZE)) { - xdr = XDR_encode_int8(*lcharptr); - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + *ptr++ = XDR_encode_int8(*lcharptr); lcharptr++; lcount++; } @@ -450,9 +622,7 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) // Now pad if required while ((lcount % 4) != 0) { - xdr = XDR_encode_int8(0); - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + *ptr++ = XDR_encode_int8(0); lcount++; //cout << "0"; } @@ -463,20 +633,17 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) else { // Nothing to encode - xdr = XDR_encode_uint32(0); - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + *ptr++ = id; + *ptr++ = XDR_encode_uint32(0); //cout << "Prop:" << (*it)->id << " " << (*it)->type << " 0\n"; } - } break; default: //cout << " Unknown Type: " << (*it)->type << "\n"; - xdr = XDR_encode_float((*it)->float_value);; - memcpy(ptr, &xdr, sizeof(xdr_data_t)); - ptr += sizeof(xdr_data_t); + *ptr++ = id; + *ptr++ = XDR_encode_float((*it)->float_value);; //cout << "Prop:" << (*it)->id << " " << (*it)->type << " "<< (*it)->float_value << "\n"; break; } @@ -484,14 +651,12 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) ++it; } escape: - - T_MsgHdr MsgHdr; - FillMsgHdr(&MsgHdr, POS_DATA_ID, ptr - Msg); - memcpy(Msg, &MsgHdr, sizeof(T_MsgHdr)); - - mSocket->sendto(Msg, ptr - Msg, 0, &mServer); + unsigned msgLen = reinterpret_cast(ptr) - msgBuf.Msg; + FillMsgHdr(msgBuf.msgHdr(), POS_DATA_ID, msgLen); + mSocket->sendto(msgBuf.Msg, msgLen, 0, &mServer); SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::SendMyPosition"); } // FGMultiplayMgr::SendMyPosition() + ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// @@ -548,16 +713,14 @@ FGMultiplayMgr::Update(void) return; /// Just for expiry - SGTimeStamp timestamper; - timestamper.stamp(); - long stamp = timestamper.get_seconds(); + long stamp = SGTimeStamp::now().getSeconds(); ////////////////////////////////////////////////// // Read the receive socket and process any data ////////////////////////////////////////////////// - int bytes; + ssize_t bytes; do { - char Msg[MAX_PACKET_SIZE]; + MsgBuf msgBuf; ////////////////////////////////////////////////// // Although the recv call asks for // MAX_PACKET_SIZE of data, the number of bytes @@ -565,7 +728,8 @@ FGMultiplayMgr::Update(void) // packet waiting to be processed. ////////////////////////////////////////////////// netAddress SenderAddress; - bytes = mSocket->recvfrom(Msg, sizeof(Msg), 0, &SenderAddress); + bytes = mSocket->recvfrom(msgBuf.Msg, sizeof(msgBuf.Msg), 0, + &SenderAddress); ////////////////////////////////////////////////// // no Data received ////////////////////////////////////////////////// @@ -574,33 +738,34 @@ FGMultiplayMgr::Update(void) perror("FGMultiplayMgr::MP_ProcessData"); break; } - if (bytes <= sizeof(T_MsgHdr)) { - SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " + if (bytes <= static_cast(sizeof(T_MsgHdr))) { + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " << "received message with insufficient data" ); break; } ////////////////////////////////////////////////// // Read header ////////////////////////////////////////////////// - T_MsgHdr* MsgHdr = (T_MsgHdr *)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); MsgHdr->MsgLen = XDR_decode_uint32 (MsgHdr->MsgLen); MsgHdr->ReplyPort = XDR_decode_uint32 (MsgHdr->ReplyPort); + MsgHdr->Callsign[MAX_CALLSIGN_LEN -1] = '\0'; if (MsgHdr->Magic != MSG_MAGIC) { - SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " << "message has invalid magic number!" ); break; } if (MsgHdr->Version != PROTO_VER) { - SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " << "message has invalid protocoll number!" ); break; } if (MsgHdr->MsgLen != bytes) { - SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " - << "message has invalid length!" ); + SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " + << "message from " << MsgHdr->Callsign << " has invalid length!"); break; } ////////////////////////////////////////////////// @@ -608,10 +773,10 @@ FGMultiplayMgr::Update(void) ////////////////////////////////////////////////// switch (MsgHdr->MsgId) { case CHAT_MSG_ID: - ProcessChatMsg(Msg, SenderAddress); + ProcessChatMsg(msgBuf, SenderAddress); break; case POS_DATA_ID: - ProcessPosMsg(Msg, SenderAddress, bytes, stamp); + ProcessPosMsg(msgBuf, SenderAddress, stamp); break; case UNUSABLE_POS_DATA_ID: case OLD_OLD_POS_DATA_ID: @@ -619,7 +784,7 @@ FGMultiplayMgr::Update(void) case OLD_POS_DATA_ID: break; default: - SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::MP_ProcessData - " + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " << "Unknown message Id received: " << MsgHdr->MsgId ); break; } @@ -645,16 +810,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) { - T_MsgHdr* MsgHdr = (T_MsgHdr *)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 - " + SG_LOG( SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - " << "Position message received with insufficient data" ); return; } - T_PositionMsg* PosMsg = (T_PositionMsg *)(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); @@ -675,11 +840,32 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, //cout << "INPUT MESSAGE\n"; - xdr_data_t* xdr = (xdr_data_t*) - (Msg + sizeof(T_MsgHdr) + sizeof(T_PositionMsg)); - while ((char*)xdr < Msg + len) { + + // 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. + const xdr_data_t* xdr = Msg.properties(); + if (PosMsg->pad != 0) { + if (verifyProperties(&PosMsg->pad, Msg.propsRecvdEnd())) + xdr = &PosMsg->pad; + else if (!verifyProperties(xdr, Msg.propsRecvdEnd())) + goto noprops; + } + while (xdr < Msg.propsRecvdEnd()) { FGPropertyData* pData = new FGPropertyData; - SGPropertyNode::Type type = SGPropertyNode::UNSPECIFIED; + // simgear::props::Type type = simgear::props::UNSPECIFIED; // First element is always the ID pData->id = XDR_decode_uint32(*xdr); @@ -687,38 +873,28 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, xdr++; // Check the ID actually exists and get the type - unsigned i = 0; - bool found = false; - while (FGMultiplayMgr::sIdPropertyList[i].name) - { - if (sIdPropertyList[i].id == pData->id) - { - found = true; - pData->type = sIdPropertyList[i].type; - } - - i++; - } + const IdPropertyList* plist = findProperty(pData->id); - if (found == true) + if (plist) { + pData->type = plist->type; // How we decode the remainder of the property depends on the type switch (pData->type) { - case SGPropertyNode::INT: - case SGPropertyNode::BOOL: - case SGPropertyNode::LONG: + case simgear::props::INT: + case simgear::props::BOOL: + case simgear::props::LONG: pData->int_value = XDR_decode_uint32(*xdr); xdr++; //cout << pData->int_value << "\n"; break; - case SGPropertyNode::FLOAT: - case SGPropertyNode::DOUBLE: + case simgear::props::FLOAT: + case simgear::props::DOUBLE: pData->float_value = XDR_decode_float(*xdr); xdr++; //cout << pData->float_value << "\n"; break; - case SGPropertyNode::STRING: - case SGPropertyNode::UNSPECIFIED: + case simgear::props::STRING: + case simgear::props::UNSPECIFIED: { // String is complicated. It consists of // The length of the string @@ -727,42 +903,34 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, uint32_t length = XDR_decode_uint32(*xdr); xdr++; //cout << length << " "; - - if ((length > 0) && (length < MAX_TEXT_SIZE)) - { - pData->string_value = new char[length + 1]; - //cout << " String: "; - - for (int i = 0; i < length; i++) + // Old versions truncated the string but left the length unadjusted. + if (length > MAX_TEXT_SIZE) + length = MAX_TEXT_SIZE; + pData->string_value = new char[length + 1]; + //cout << " String: "; + for (unsigned i = 0; i < length; i++) { pData->string_value[i] = (char) XDR_decode_int8(*xdr); xdr++; //cout << pData->string_value[i]; } - pData->string_value[length] = '\0'; + pData->string_value[length] = '\0'; - // Now handle the padding - while ((length % 4) != 0) + // Now handle the padding + while ((length % 4) != 0) { xdr++; length++; //cout << "0"; } - } - else - { - pData->string_value = new char[1]; - pData->string_value[0] = '\0'; - } - //cout << "\n"; } break; default: pData->float_value = XDR_decode_float(*xdr); - cerr << "Unknown Prop type " << pData->id << " " << pData->type << "\n"; + SG_LOG(SG_NETWORK, SG_DEBUG, "Unknown Prop type " << pData->id << " " << pData->type); xdr++; break; } @@ -772,10 +940,12 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, else { // We failed to find the property. We'll try the next packet immediately. - //cout << " Unknown\n"; + SG_LOG(SG_NETWORK, SG_INFO, "FGMultiplayMgr::ProcessPosMsg - " + "message from " << MsgHdr->Callsign << " has unknown property id " + << pData->id); } } - + noprops: FGAIMultiplayer* mp = getMultiplayer(MsgHdr->Callsign); if (!mp) mp = addMultiplayer(MsgHdr->Callsign, PosMsg->Model); @@ -790,25 +960,27 @@ 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 - " + SG_LOG( SG_NETWORK, SG_DEBUG, "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)]; + const T_ChatMsg* ChatMsg + = reinterpret_cast(Msg.Msg + sizeof(T_MsgHdr)); + strncpy(chatStr, ChatMsg->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)); - SG_LOG (SG_NETWORK, SG_ALERT, "Chat [" << MsgHdr->Callsign << "]" - << " " << MsgBuf); + SG_LOG (SG_NETWORK, SG_WARN, "Chat [" << MsgHdr->Callsign << "]" + << " " << chatStr); - delete [] MsgBuf; + delete [] chatStr; } // FGMultiplayMgr::ProcessChatMsg () ////////////////////////////////////////////////////////////////////// @@ -854,11 +1026,8 @@ FGMultiplayMgr::addMultiplayer(const std::string& callsign, aiMgr->attach(mp); /// FIXME: that must follow the attach ATM ... - unsigned i = 0; - while (sIdPropertyList[i].name) { + for (unsigned i = 0; i < numProperties; ++i) mp->addPropertyId(sIdPropertyList[i].id, sIdPropertyList[i].name); - ++i; - } } return mp;