diff --git a/xpcPlugin/Message.cpp b/xpcPlugin/Message.cpp new file mode 100644 index 0000000..50000e8 --- /dev/null +++ b/xpcPlugin/Message.cpp @@ -0,0 +1,166 @@ +//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the +//National Aeronautics and Space Administration. All Rights Reserved. +#include "Message.h" +#include "Log.h" +#include "xplaneConnect.h" + +#include +#include +#include + +namespace XPC +{ + Message::Message() {} + + Message Message::ReadFrom(UDPSocket& sock) + { + Message m; + int len = sock.Read(m.buffer, bufferSize, &m.source); + m.size = len < 0 ? 0 : len; + return m; + } + + std::uint32_t Message::GetMagicNumber() + { + if (size < 4) + { + return 0; + } + return *((std::uint32_t*)buffer); + } + + std::string Message::GetHead() + { + if (size < 4) + { + return ""; + } + return std::string((char*)buffer, 4); + } + + const std::uint8_t* Message::GetBuffer() + { + if (size == 0) + { + return nullptr; + } + return buffer; + } + + std::size_t Message::GetSize() + { + return size; + } + + struct sockaddr Message::GetSource() + { + return source; + } + + void Message::PrintToLog() + { +#if LOG_VERBOSITY > 2 + std::stringstream ss; + ss << "[DEBUG]"; + + // Dump raw bytes to string + ss << std::hex << std::setfill('0'); + for (int i = 0; i < size; ++i) + { + ss << ' ' << std::setw(2) << static_cast(buffer[i]); + } + Log::WriteLine(ss.str()); + + ss.str(""); + ss << "[" << GetHead() << "-DEBUG](" << buffer[4] << ")"; + switch (GetMagicNumber()) + { + case 0x434F4E4E: // CONN + case 0x57595054: // WYPT + case 0x54455854: // TEXT + { + Log::WriteLine(ss.str()); + break; + } + case 0x4354524C: // CTRL + { + xpcCtrl ctrl = parseCTRL((char*)buffer); + ss << " (" << ctrl.pitch << " " << ctrl.roll << " " << ctrl.yaw << ") "; + ss << ctrl.throttle << " " << ctrl.gear << " " << ctrl.flaps; + Log::WriteLine(ss.str()); + break; + } + case 0x44415441: // DATA + { + float dataRef[30][9]; + short numCols = parseDATA((char*)buffer, size, dataRef); + ss << " (" << numCols << " lines)"; + Log::WriteLine(ss.str()); + for (int i = 0; i < numCols; ++i) + { + ss.str(""); + ss << "\t#" << dataRef[i][0]; + for (int j = 1; j < 9; ++j) + { + ss << " " << dataRef[i][j]; + } + Log::WriteLine(ss.str()); + } + break; + } + case 0x44524546: // DREF + { + Log::WriteLine(ss.str()); + std::string dref((char*)buffer + 6, buffer[5]); + Log::FormatLine("-\tDREF (size %i) = %s", dref.length(), dref.c_str()); + ss.str(""); + int values = buffer[6 + buffer[5]]; + ss << "\tValues(size " << values << ") ="; + for (int i = 0; i < values; ++i) + { + ss << " " << *((float*)(buffer + values + 1 + sizeof(float) * i)); + } + Log::WriteLine(ss.str()); + break; + } + case 0x47455444: // GETD + { + Log::WriteLine(ss.str()); + int cur = 6; + for (int i = 0; i < buffer[5]; ++i) + { + std::string dref((char*)buffer + cur + 1, buffer[cur]); + Log::FormatLine("\t#%i/%i (size:%i) %s", i + 1, buffer[5], dref.length(), dref); + cur += 1 + buffer[cur]; + } + break; + } + case 0x504F5349: // POSI + { + float position[6] = { 0.0 }; + short aircraft = 0; + float gear = -1.0; + aircraft = parsePOSI((char*)buffer, position, 6, &gear); + ss << ' ' << aircraft; + ss << " (" << position[0] << ' ' << position[1] << ' ' << position[2] << ") ("; + ss << position[3] << ' ' << position[4] << ' ' << position[5] << ") "; + ss << gear; + Log::WriteLine(ss.str()); + break; + } + case 0x53494D55: // SIMU + { + ss << ' ' << buffer[5]; + Log::WriteLine(ss.str()); + break; + } + default: + { + ss << " UNKNOWN HEADER"; + Log::WriteLine(ss.str()); + break; + } + } +#endif + } +} \ No newline at end of file diff --git a/xpcPlugin/Message.h b/xpcPlugin/Message.h new file mode 100644 index 0000000..9bcfe49 --- /dev/null +++ b/xpcPlugin/Message.h @@ -0,0 +1,57 @@ +//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the +//National Aeronautics and Space Administration. All Rights Reserved. +#ifndef XPC_MESSAGE_H +#define XPC_MESSAGE_H + +#include "UDPSocket.h" + +namespace XPC +{ + /// Represents a message received from an XPC client. + /// + /// \author Jason Watkins + /// \version 1.0 + /// \since 1.0 + /// \date Intial Version: 2015-04-11 + /// \date Last Updated: 2015-04-11 + class Message + { + public: + /// Reads a datagram from the specified socket and interprets it as a + /// message. + /// + /// \param sock The socket to read from. + /// \returns A message parsed from the data read from sock. If no + /// data was read or an error occurs, returns a message + /// with the size set to 0. + static Message ReadFrom(UDPSocket& sock); + + /// Gets the message header in binary form. + std::uint32_t GetMagicNumber(); + + /// Gets the message header. + std::string GetHead(); + + /// Gets the buffer underlying the message. + const std::uint8_t* GetBuffer(); + + /// Gets the size of the message in bytes. + std::size_t GetSize(); + + /// Gets the address this message was read from. + struct sockaddr GetSource(); + + /// Prints the contents of the message to the XPC log. + void PrintToLog(); + + private: + Message(); + + static const std::size_t bufferSize = 4096; + std::uint8_t buffer[bufferSize]; + std::size_t size; + struct sockaddr source; + }; +} + +#endif \ No newline at end of file diff --git a/xpcPlugin/XPCPlugin.cpp b/xpcPlugin/XPCPlugin.cpp index cde7903..1a3edde 100755 --- a/xpcPlugin/XPCPlugin.cpp +++ b/xpcPlugin/XPCPlugin.cpp @@ -63,6 +63,7 @@ // XPC Includes #include "Log.h" #include "Drawing.h" +#include "Message.h" #include "UDPSocket.h" #include "xpcPluginTools.h" @@ -130,7 +131,7 @@ int handleDREF(char *buf); int handleVIEW(); int handleDATA(char *buf, int buflen); int handleTEXT(char *buf, int len); -short handleInput(struct XPCMessage * theMessage); +short handleInput(XPC::Message& msg); char setPOSI(short aircraft, float pos[3]); char setORIENT(short aircraft, float orient[3]); @@ -239,7 +240,6 @@ float MyFlightLoopCallback( float inElapsedSinceLastCall, #if (__APPLE__) double diff_t; #endif - XPCMessage theMessage; counter++; if (benchmarkingSwitch > 1) @@ -255,8 +255,8 @@ float MyFlightLoopCallback( float inElapsedSinceLastCall, start = (double)mach_absolute_time( ) * timeConvert; #endif } - readMessage(recvSocket, &theMessage); - result = handleInput(&theMessage); + XPC::Message msg = XPC::Message::ReadFrom(*recvSocket); + result = handleInput(msg); if (benchmarkingSwitch > 0) { @@ -282,145 +282,143 @@ float MyFlightLoopCallback( float inElapsedSinceLastCall, return -1; } -short handleInput(struct XPCMessage * theMessage) +short handleInput(XPC::Message& msg) { int i; - char IP[16] = {0}; + char IP[16] = { 0 }; unsigned short port = 0; - + current_connection = -1; - - if (theMessage->msglen > 0) // If message received + + if (msg.GetSize() == 0) { - if (LOG_VERBOSITY > 0) + // No message received + return 0; + } + + msg.PrintToLog(); + + // Check for existing connection + port = getIP(msg.GetSource(), IP); + for (i = 0; i < number_of_connections; i++) + { + if (strcmp(connectionList[i].IP, IP) == 0 && port == connectionList[i].fromPort && port > 0) { -#ifdef _WIN32 -#else - printBufferToLog(*theMessage); -#endif + current_connection = i; + break; } - - // Check for existing connection - port = getIP(theMessage->recvaddr,IP); - for (i=0; i= MAXCONN) // Handle hitting MAXCONN (COME UP WITH A BETTER SOLUTION) { - if (strcmp(connectionList[i].IP,IP) == 0 && port == connectionList[i].fromPort && port > 0) - { - current_connection=i; - break; - } + XPC::Log::WriteLine("[EXEC] Hit maximum number of connections-Removing old ones"); + number_of_connections = 0; } - - if (current_connection == -1) //SETUP NEW CONNECTION - { - if (number_of_connections>=MAXCONN) // Handle hitting MAXCONN (COME UP WITH A BETTER SOLUTION) - { - XPC::Log::WriteLine("[EXEC] Hit maximum number of connections-Removing old ones"); - number_of_connections = 0; - } - - memcpy(connectionList[number_of_connections].IP,IP,16); - connectionList[number_of_connections].recPort = 49008; - connectionList[number_of_connections].fromPort = port; - current_connection = number_of_connections; - number_of_connections ++; - - // Log Connection - XPC::Log::FormatLine("[EXEC] New Connection [%i]. IP=%s, port=%i", number_of_connections, IP, port); - } - - if (strncmp(theMessage->head,"CONN",4)==0) // Header = CONN (Connection) - { - handleCONN(theMessage->msg); - } - else if (strncmp(theMessage->head,"SIMU",4)==0) // Header = SIMU - { - handleSIMU(theMessage->msg); - } - else if (strncmp(theMessage->head,"POSI",4)==0) // Header = POSI (Position) - { - handlePOSI(theMessage->msg); - } - else if (strncmp(theMessage->head,"CTRL",4)==0) // Header = CTRL (Control) - { - handleCTRL(theMessage->msg); - } - else if (strncmp(theMessage->head,"WYPT",4)==0) // Header = WYPT (Waypoint Draw) - { - handleWYPT(theMessage->msg, theMessage->msglen); - } - else if (strncmp(theMessage->head,"GETD",4)==0) // Header = GETD (Data Request) - { - handleGETD(theMessage->msg); - } - else if (strncmp(theMessage->head,"DREF",4)==0) // Header = DREF (By Data Ref) (this is slower than DATA) - { - handleDREF(theMessage->msg); - } - else if (strncmp(theMessage->head,"VIEW",4)==0) // Header = VIEW (Change View) - { - handleVIEW(); - } - else if (strncmp(theMessage->head,"DATA",4)==0) // Header = DATA (UDP Data) - { - handleDATA(theMessage->msg, theMessage->msglen); - } - else if (strncmp(theMessage->head, "TEXT", 4) == 0) // Header = TEXT (Screen message) - { - handleTEXT(theMessage->msg, theMessage->msglen); - } - else if ((strncmp(theMessage->head,"DSEL",4)==0) || (strncmp(theMessage->head,"USEL",4)==0)) // Header = DSEL/USEL (Select UDP Send) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if ((strncmp(theMessage->head,"DCOC",4)==0) || (strncmp(theMessage->head,"UCOC",4)==0)) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if ((strncmp(theMessage->head,"MOUS",4)==0) || (strncmp(theMessage->head,"CHAR",4)==0)) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if (strncmp(theMessage->head,"MENU",4)==0) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if (strncmp(theMessage->head,"SOUN",4)==0) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if ((strncmp(theMessage->head,"FAIL",4)==0) || (strncmp(theMessage->head,"RECO",4)==0)) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if (strncmp(theMessage->head,"PAPT",4)==0) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if ((strncmp(theMessage->head,"VEHN",4)==0) || (strncmp(theMessage->head,"VEH1",4)==0) || (strncmp(theMessage->head,"VEHA",4)==0)) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if ((strncmp(theMessage->head,"OBJN",4)==0) || (strncmp(theMessage->head,"OBJL",4)==0)) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if ((strncmp(theMessage->head,"GSET",4)==0) || (strncmp(theMessage->head,"ISET",4)==0)) - { - sendBUF(theMessage->msg,theMessage->msglen); // Send to UDP - } - else if (strncmp(theMessage->head, "BOAT", 4) == 0) - { - sendBUF(theMessage->msg, theMessage->msglen); // Send to UDP - } - else - { //unrecognized header - XPC::Log::FormatLine("[EXEC] ERROR: Command %s not recognized", theMessage->head); - } - current_connection = -1; - } // end if (buflen > 0) - - return theMessage->msglen; + + memcpy(connectionList[number_of_connections].IP, IP, 16); + connectionList[number_of_connections].recPort = 49008; + connectionList[number_of_connections].fromPort = port; + current_connection = number_of_connections; + number_of_connections++; + + // Log Connection + XPC::Log::FormatLine("[EXEC] New Connection [%i]. IP=%s, port=%i", number_of_connections, IP, port); + } + + std::string head = msg.GetHead(); + if (head == "CONN") // Header = CONN (Connection) + { + handleCONN((char*)msg.GetBuffer()); + } + else if (head == "SIMU") // Header = SIMU + { + handleSIMU((char*)msg.GetBuffer()); + } + else if (head == "POSI") // Header = POSI (Position) + { + handlePOSI((char*)msg.GetBuffer()); + } + else if (head == "CTRL") // Header = CTRL (Control) + { + handleCTRL((char*)msg.GetBuffer()); + } + else if (head == "WYPT") // Header = WYPT (Waypoint Draw) + { + handleWYPT((char*)msg.GetBuffer(), msg.GetSize()); + } + else if (head == "GETD") // Header = GETD (Data Request) + { + handleGETD((char*)msg.GetBuffer()); + } + else if (head == "DREF") // Header = DREF (By Data Ref) (this is slower than DATA) + { + handleDREF((char*)msg.GetBuffer()); + } + else if (head == "VIEW") // Header = VIEW (Change View) + { + handleVIEW(); + } + else if (head == "DATA") // Header = DATA (UDP Data) + { + handleDATA((char*)msg.GetBuffer(), msg.GetSize()); + } + else if (head == "TEXT") // Header = TEXT (Screen message) + { + handleTEXT((char*)msg.GetBuffer(), msg.GetSize()); + } + else if ((head == "DSEL") || (head == "USEL")) // Header = DSEL/USEL (Select UDP Send) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if ((head == "DCOC") || (head == "UCOC")) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if ((head == "MOUS") || (head == "CHAR")) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if (head == "MENU") + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if (head == "SOUN") + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if ((head == "FAIL") || (head == "RECO")) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if (head == "PAPT") + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if ((head == "VEHN") || head == "VEH1" || (head == "VEHA")) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if ((head == "OBJN") || (head == "OBJL")) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if ((head == "GSET") || (head == "ISET")) + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else if (head == "BOAT") + { + sendBUF((char*)msg.GetBuffer(), msg.GetSize()); // Send to UDP + } + else + { //unrecognized header + XPC::Log::FormatLine("[EXEC] ERROR: Command %s not recognized", head); + } + current_connection = -1; + + return 0; } void sendBUF( char buf[], int buflen) diff --git a/xpcPlugin/XPlaneConnect/64/win.xpl b/xpcPlugin/XPlaneConnect/64/win.xpl index 8de63dd..084ec81 100644 Binary files a/xpcPlugin/XPlaneConnect/64/win.xpl and b/xpcPlugin/XPlaneConnect/64/win.xpl differ diff --git a/xpcPlugin/XPlaneConnect/win.xpl b/xpcPlugin/XPlaneConnect/win.xpl index 9d83882..c2a1560 100644 Binary files a/xpcPlugin/XPlaneConnect/win.xpl and b/xpcPlugin/XPlaneConnect/win.xpl differ diff --git a/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj b/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj index b55e7a3..51ab988 100644 --- a/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj +++ b/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj @@ -101,6 +101,7 @@ + @@ -108,6 +109,7 @@ + diff --git a/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj.filters b/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj.filters index a35a766..eae1402 100644 --- a/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj.filters +++ b/xpcPlugin/xpcPlugin/xpcPlugin.vcxproj.filters @@ -30,6 +30,9 @@ Header Files + + Header Files + @@ -50,6 +53,9 @@ Source Files + + Source Files + diff --git a/xpcPlugin/xpcPluginTools.cpp b/xpcPlugin/xpcPluginTools.cpp index 776600b..94b7de6 100644 --- a/xpcPlugin/xpcPluginTools.cpp +++ b/xpcPlugin/xpcPluginTools.cpp @@ -36,22 +36,6 @@ XPLMDataRef XPLMDataRefs[134][8]; XPLMDataRef multiplayer[20][17]; XPLMDataRef AIswitch; -void readMessage(XPC::UDPSocket* socket, struct XPCMessage * pMessage) -{ - pMessage->msglen = socket->Read((std::uint8_t*)pMessage->msg, 5000, &pMessage->recvaddr); - - if ( pMessage->msglen <= 0 ) // No Message - { - pMessage->msg[0] = 0; - } - else - { - strncpy( pMessage->head, pMessage->msg, 4 ); - } - - return; -} - void buildXPLMDataRefs() { int i, j; @@ -300,146 +284,6 @@ unsigned short getIP(struct sockaddr recvaddr, char *IP) // DEBUGGING TOOLS // -------------------------------- -int printBufferToLog(struct XPCMessage & msg) -{ - // Prints the entire buffer to the log (for debugging) - char logmsg[350] = "[DEBUG]"; - int i; - - for (i=0;i