Cleaned up DREF functions and tweaked printError.

- printError is now a varags function, and will print format strings for the message.
 - Removed several internal DREF functions from the header file.
 - Significantly improved error reporting in DREF functions.
 - Removed dynamic allocation for responses. Clients are now expected to provide fully allocated storage for getDREFs. An error message will be printed if the provided structure is too small.
 - Fixes nasa/XPlaneConnect#30
This commit is contained in:
Jason Watkins
2015-04-15 16:54:41 -07:00
parent 4e7e816da1
commit 80a1a2dcd2
2 changed files with 148 additions and 118 deletions

View File

@@ -66,12 +66,19 @@ void usleep(__int64 usec)
} }
#endif #endif
void printError(char *functionName, char *errorMessage); void printError(char *functionName, char *format, ...);
short sendRequest(XPCSocket recfd, char DREFArray[][100], short DREFSizes[], short listLength); short sendRequest(XPCSocket recfd, char DREFArray[][100], short DREFSizes[], short listLength);
void printError(char *functionName, char *errorMessage) void printError(char *functionName, char *format)
{ {
printf("[%s] ERROR: %s\n", functionName, errorMessage); va_list args;
va_start(args, format);
printf("[%s] ERROR: ", functionName);
vprintf(format, args);
printf("\n");
va_end(args);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -339,67 +346,153 @@ int readDATA(XPCSocket sock, float dataRef[][9], int rows)
/**** End X-Plane UDP Data functions ****/ /**** End X-Plane UDP Data functions ****/
/*****************************************************************************/ /*****************************************************************************/
short sendDREF(XPCSocket recfd, const char *dataRef, unsigned short length_of_DREF, float *values, unsigned short number_of_values) { /*****************************************************************************/
char message[5000]; /**** DREF functions ****/
int length = 7+length_of_DREF+number_of_values*sizeof(float); /*****************************************************************************/
int setDREF(XPCSocket sock, const char* dref, float values[], int size)
//HEADER
strncpy(message,"DREF",4);
//DREF
message[5] = (char) length_of_DREF;
memcpy(&message[6],dataRef,length_of_DREF);
//VALUES
message[length_of_DREF+6] = (char) number_of_values;
memcpy(&message[length_of_DREF+7],&values[0],sizeof(float)*number_of_values);
sendUDP(recfd, message, length);
return 0;
}
short sendRequest(XPCSocket recfd, char DREFArray[][100], short DREFSizes[], short listLength)
{ {
int i; // Setup command
char message[5000]={0}; // 5 byte header + max 255 char dref name + max 255 values * 4 bytes per value = 1279
int length = 6; unsigned char buffer[1279] = "DREF";
int drefLen = strnlen(dref, 256);
//HEADER if (drefLen > 255)
strncpy(message,"GETD",4);
message[5] = (char) listLength; //Number of Values
//The rest
for (i=0; i < listLength; i++)
{ {
message[length] = (char) DREFSizes[i]; printError("setDREF", "dref length is too long. Must be less than 256 characters.");
memcpy(&message[length+1],DREFArray[i],message[length]); return -1;
length += message[length] + 1;
} }
if (size > 255)
{
printError("setDREF", "size is too big. Must be less than 256.");
return -2;
}
int len = 7 + drefLen + size * sizeof(float);
sendUDP(recfd, message, length); // Copy dref to buffer
buffer[5] = (unsigned char)drefLen;
memcpy(buffer + 6, dref, drefLen);
// Copy values to buffer
buffer[6 + drefLen] = (unsigned char)size;
memcpy(buffer + 7 + drefLen, values, size * sizeof(float));
// Send command
if (sendUDP(sock, buffer, len) != 0)
{
printError("setDREF", "Failed to send command");
return -2;
}
return 0; return 0;
} }
short requestDREF(XPCSocket sendfd, XPCSocket recfd, char DREFArray[][100], short DREFSizes[], short listLength, float *resultArray[], short arraySizes[]) int sendDREFRequest(XPCSocket sock, const char* drefs[], unsigned char count)
{ {
int i; // Setup command
// 6 byte header + potentially 255 drefs, each 256 chars long.
sendRequest(sendfd, DREFArray, DREFSizes, listLength); // Easiest to just round to an even 2^16.
unsigned char buffer[65536] = "GETD";
for (i=0; i<80; i++) buffer[5] = count;
int len = 6;
for (int i = 0; i < count; ++i)
{ {
int size = readDREF(recfd, resultArray, arraySizes); size_t drefLen = strnlen(drefs[i], 256);
if (size != -1) // Received input if (drefLen > 255)
{ {
return size; printError("getDREFs", "dref %d is too long.", i);
return -1;
}
buffer[len++] = (unsigned char)drefLen;
strncpy(buffer + len, drefs[i], drefLen);
len += drefLen;
}
// Send Command
if (sendUDP(sock, buffer, len) != 0)
{
printError("getDREFs", "Failed to send command");
return -2;
}
return 0;
}
int getDREFResponse(XPCSocket sock, float* values[], unsigned char count, int sizes[])
{
unsigned char buffer[65536];
// Read data. Try 40 times to read, then give up.
// TODO: Why not just set the timeout to 40ms?
int result;
for (int i = 0; i < 40; ++i)
{
result = readUDP(sock, buffer, 65536, NULL);
if (result > 0)
{
break;
}
if (result < 0)
{
printError("getDREFs", "Read operation failed.");
return -1;
} }
} }
return -1; if (result < 6)
{
printError("getDREFs", "Response was too short. Expected at least 6 bytes, but only got %d.", result);
return -2;
}
if (buffer[5] != count)
{
printError("getDREFs", "Unexpected response size. Expected %d rows, got %d instead.", count, buffer[5]);
return -3;
}
int cur = 6;
for (int i = 0; i < count; ++i)
{
int l = buffer[cur++];
if (l > sizes[i])
{
printError("getDREFs", "values is too small. Row had %d values, only room for %d.", l, sizes[i]);
// Copy as many values as we can anyway
memcpy(values[i], buffer + cur, sizes[i] * sizeof(float));
}
else
{
memcpy(values[i], buffer + cur, l * sizeof(float));
sizes[i] = l;
}
cur += l * sizeof(float);
}
return 0;
} }
int getDREF(XPCSocket sock, const char* dref, float values[], int* size)
{
return getDREFs(sock, &dref, &values, 1, size);
}
int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char count, int sizes[])
{
// Send Command
int result = sendDREFRequest(sock, drefs, count);
if (result < 0)
{
// A error ocurred while sending.
// sendDREFRequest will print an error message, so just return.
return -1;
}
// Read Response
if (getDREFResponse(sock, values, count, sizes) < 0)
{
// A error ocurred while reading the response.
// getDREFResponse will print an error message, so just return.
return -2;
}
return 0;
}
/*****************************************************************************/
/**** End DREF functions ****/
/*****************************************************************************/
short sendPOSI(XPCSocket recfd, short ACNum, short numArgs, float valueArray[]) short sendPOSI(XPCSocket recfd, short ACNum, short numArgs, float valueArray[])
{ {
char message[40] = {0}; char message[40] = {0};
@@ -542,18 +635,6 @@ short readRequest(XPCSocket recfd, float *dataRef[], short arraySizes[], struct
return -1; return -1;
} }
short readDREF(XPCSocket recfd, float *resultArray[], short arraySizes[])
{
char buf[5000] = {0};
readUDP(recfd,buf, NULL);
if (buf[0]!= '\0')
{
return parseRequest(buf, resultArray, arraySizes);
}
return -1;
}
short readPOSI(XPCSocket recfd, float resultArray[], int arraySize, float *gear) short readPOSI(XPCSocket recfd, float resultArray[], int arraySize, float *gear)
{ {
char buf[5000] = {0}; char buf[5000] = {0};
@@ -586,53 +667,6 @@ xpcCtrl readCTRL(XPCSocket recfd)
//PARSE //PARSE
//--------------------- //---------------------
short parseDREF(const char my_message[], char *dataRef, unsigned short *length_of_DREF, float *values, unsigned short *number_of_values)
{
*length_of_DREF = (unsigned short) my_message[5];
memcpy(dataRef,&(my_message[6]),*length_of_DREF);
*number_of_values = (unsigned short) my_message[6+*length_of_DREF];
memcpy(values,&my_message[*length_of_DREF+7],*number_of_values*sizeof(float));
return 0;
}
int parseGETD(const char my_message[], char *DREFArray[], int DREFSizes[])
{
int i;
int listLength = my_message[5];
int counter = 6;
for (i=0; i<listLength;i++)
{
DREFSizes[i] = my_message[counter];
memcpy(DREFArray[i],&my_message[counter+1],DREFSizes[i]);
counter += DREFSizes[i]+1;
}
return listLength;
}
short parseRequest(const char my_message[], float *resultArray[], short arraySizes[])
{
int i;
short count = my_message[5];
short place = 6;
for (i=0; i<count; i++)
{
arraySizes[i] = my_message[place];
//if (resultArray[i] != NULL)
//{
// free(resultArray[i]);
//}
resultArray[i] = malloc(arraySizes[i]*sizeof(float));
memcpy(resultArray[i],&my_message[place + 1],arraySizes[i]*sizeof(float));
place += 1 + arraySizes[i]*sizeof(float);
}
return count;
}
short parsePOSI(const char my_message[], float resultArray[], int arraySize, float *gear) short parsePOSI(const char my_message[], float resultArray[], int arraySize, float *gear)
{ {
int i; int i;

View File

@@ -101,6 +101,11 @@ int pauseSim(XPCSocket sock, char pause);
// X-Plane UDP DATA // X-Plane UDP DATA
int readDATA(XPCSocket sock, float dataRef[][9], int rows); int readDATA(XPCSocket sock, float dataRef[][9], int rows);
int sendDATA(XPCSocket sock, float dataRef[][9], int rows); int sendDATA(XPCSocket sock, float dataRef[][9], int rows);
// DREF Manipulation
int setDREF(XPCSocket sock, const char* dref, float values[], int size);
int getDREF(XPCSocket sock, const char* dref, float values[], int* size);
int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char count, int sizes[]);
// Position // Position
short parsePOSI(const char my_message[], float resultArray[], int arraySize, float *gear); short parsePOSI(const char my_message[], float resultArray[], int arraySize, float *gear);
@@ -112,15 +117,6 @@ xpcCtrl parseCTRL(const char data[]);
xpcCtrl readCTRL(XPCSocket recfd); xpcCtrl readCTRL(XPCSocket recfd);
short sendCTRL(XPCSocket recfd, short numArgs, float valueArray[]); short sendCTRL(XPCSocket recfd, short numArgs, float valueArray[]);
short sendpCTRL(XPCSocket recfd, short numArgs, float valueArray[], char acNum); short sendpCTRL(XPCSocket recfd, short numArgs, float valueArray[], char acNum);
// DREF Manipulation
short readDREF(XPCSocket recfd, float *resultArray[], short arraySizes[]);
short parseDREF(const char my_message[], char *dataRef, unsigned short *length_of_DREF, float *values, unsigned short *number_of_values);
short sendDREF(XPCSocket recfd, const char *dataRef, unsigned short length_of_DREF, float *values, unsigned short number_of_values);
short requestDREF(XPCSocket sendfd, XPCSocket recfd, char DREFArray[][100], short DREFSizes[], short listLength, float *resultArray[], short arraySizes[]);
int parseGETD(const char my_message[], char *DREFArray[], int DREFSizes[]);
short parseRequest(const char my_message[], float *resultArray[], short arraySizes[]);
short readRequest(XPCSocket recfd, float *dataRef[], short arraySizes[], struct sockaddr *recvaddr);
// Waypoints // Waypoints
xpcWypt parseWYPT(const char data[]); xpcWypt parseWYPT(const char data[]);