I have this code below which establishes connection to server (from device). Basically assembles some buffer, sends it to server, gets response, parses and prints it. I would appreciate if someone can review it critically - see potential bugs, undefined behaviour, etc.
First some declarations:
typedef int s32;
typedef unsigned char u8;
#define SDK_KEY_MASK_ENTER 1
#define SDK_KEY_MASK_ESC 1
int sdkAccessFile(char*);
void postOperationsMenu(void);
int parseAndUpdateTerminalInfoFile(u8*,u8*);
void sdkPrintStr(u8*,int,int,int,int);
int inputAmountFloat(int*);
int ReadIDAny(u8*,int*);
int readTerminalName(u8*);
void sdkDispMsgBox(u8*,u8*, int, int);
int readTerminalKey(u8*);
int sdkMD5(u8*,u8*,int);
void DemoDisplayInfo(int,u8*,u8*);
s32 sdkCommCreateLink(void);
int sdkCommSendData(u8*, int,int);
int sdkCommRecvData(u8*,int,int,u8*);
int readTerminalInfo(u8*,u8*,u8*,u8*);
void sdkPrintStart(void);
char* serverErrorDesc(int);
void sdkPrintInit(void);
void sdkDispClearScreen(void);
int sdkReadFile(u8*,u8*,int,int*);
Code:
void addPoints()
{
u8 mifareCardNumber[20] = {0};
s32 idLength = 0;
//s32 keyPress = 0;
s32 amount = 0;
// Let operator enter amount first
if(false == inputAmountFloat(&amount))
return;
// Read ID
if(0 == ReadIDAny(mifareCardNumber, &idLength))
return;
//
// Sending data to server part ..
//
u8 sendBuffer[255] = {0};
s32 siRet = 0;
// Read terminal name which should be 10 bytes
u8 tName[20] = {0};
if(false == readTerminalName(tName))
{
sdkDispMsgBox("Status", "Error reading \rterminal name", 0, SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
return;
}
// Read authentication key
u8 key[32] = {0};
if(false == readTerminalKey(key))
{
sdkDispMsgBox("Status", "Error reading key", 0, SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
return;
}
//
// Assemble buffer to send to server
//
sendBuffer[0] = 1; // Operation code; byte 1
memcpy(&sendBuffer[1], tName, 10); // Append terminal name; next 10 bytes
memcpy(&sendBuffer[11], &amount, 4); // Append amount to be added; next 4 bytes, integer
memcpy(&sendBuffer[15], mifareCardNumber, idLength); // Append card UID; next 4 or 7 bytes
u8 whatToHash[255] = {0};
u8 hashOutput[16] = {0};
//
// Compute signature over the packet
//
memcpy(whatToHash, key, 16);
memcpy(&whatToHash[16], sendBuffer, 1 + 10 + 4 + idLength);
if(SDK_OK != sdkMD5(hashOutput, whatToHash, 16 + 1 + 10 + 4 + idLength))
{
sdkDispMsgBox("Status", "Error calculating \rhash", 0, SDK_KEY_MASK_ENTER | SDK_KEY_MASK_ESC);
return;
}
// Append hash to buffer too
memcpy(&sendBuffer[15 + idLength], hashOutput, 16);
//
// Actual sending of data ...
//
// Create Link
DemoDisplayInfo(SDK_DISP_LINE3, "Connecting", NULL);
siRet = sdkCommCreateLink();
if (SDK_OK != siRet)
{
sdkDispMsgBox("Status", "Error create link", 0, SDK_KEY_MASK_ENTER | SDK_KEY_MASK_ESC);
return;
}
// Send the data
siRet = sdkCommSendData(sendBuffer, 1 + 10 + 4 + idLength + 16, 0);
if (SDK_OK != siRet)
{
sdkDispMsgBox("Status", "Error send data", 0, SDK_KEY_MASK_ENTER | SDK_KEY_MASK_ESC);
return;
}
// Receive date from server
u8 revtmp[512] = {0};
s32 len = sdkCommRecvData(revtmp, 512 /* max amount to receive */, 10000 , NULL);
if (len <= 0)
{
sdkDispMsgBox("Status", "Error receive data", 0, SDK_KEY_MASK_ENTER | SDK_KEY_MASK_ESC);
return;
}
//
// Parse server response, which comes in form "param1;param2;param3;..."
//
// Note: check if these lengths will be sufficient also for UTF8 string, also compare with revtmp size if it will fit
u8 * pch = NULL;
u8 name[255] = {0};
u8 userAmount[255] = {0};
u8 date[50] = {0};
u8 tranID[50] = {0};
u8 cashback[50] = {0};
int counter = 0;
//
// Extract operation status from the server response first. First byte
// indicates if it is success, error, or information update.
//
pch = strtok(revtmp,";"); // extract it
int respCode = atoi(pch); // convert to integer
if(respCode != 1)
{
if(respCode == 7) // 7 is information update
{
parseAndUpdateTerminalInfoFile(pch, tName);
return;
}
else
{
// Otherwise error
sdkDispMsgBox("Status", serverErrorDesc(atoi(pch)), 0, SDK_KEY_MASK_ENTER | SDK_KEY_MASK_ESC);
return;
}
}
// Now, extract parameters from server response
// Note: If the response format is different we may get unexpected result.
// Note: Pay attention that these variables have fixed length here, to avoid oveflow
while (pch != NULL)
{
if(counter == 1)
{
// Get card owner name
strcpy(name, pch);
}else if(counter == 2)
{
strcpy(userAmount, pch);
}else if(counter == 3)
{
// Get transaction ID
strcpy(tranID, pch);
}
else if (counter == 4)
{
// Get date
strcpy(date, pch);
}else if (counter == 5)
{
// Get cashback value
strcpy(cashback, pch);
}
pch = strtok (NULL, ";");
counter++;
}
sdkDispClearScreen();
// We parsed data, first show card owner and balance on the screen
u8 finalResult[255] = {0};
sprintf(finalResult, "Owner: %s \rBalance: %.2f", name, (double)strtol(userAmount,NULL,10)/(double)100.0);
sdkDispMsgBox("Transaction OK", finalResult, 0, SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
// Read terminal information
// Note: notice fixed size maximum lengths
u8 terminalName[10 + 1] = {0};
u8 terminalAddress[100 + 1] = {0};
u8 companyName[50 + 1] = {0};
u8 hotlineNumber[10 + 1 + 10] = {0};
if(false == readTerminalInfo(terminalName, companyName, terminalAddress, hotlineNumber))
{
sdkDispMsgBox("Status", "Error reading file", 0, SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
return;
}
//
// Printing ..
//
sdkPrintInit();
u8 printBuffer[200]={0};
memset(printBuffer, 0, 200);
sprintf(printBuffer,"%s", companyName);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer," ");
sdkPrintStr(printBuffer,1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer,"Terminal: %s", terminalName);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer,"Address: %s", terminalAddress);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer, "Date: %s", date);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer, "Transaction ID: %s", tranID);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer, "Amount transferred: %.2f", (double)amount/(double)100.0);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer, "Cashback: %.2f",(double)strtol(cashback,NULL,10)/(double)100.0);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer, "Current balance: %.2f", (double)strtol(userAmount,NULL,10)/(double)100.0);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer, "Card owner: %s", name);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer," ");
sdkPrintStr(printBuffer, 1,1, 0, 3);
memset(printBuffer, 0, 200);
sprintf(printBuffer,"Hotline: %s", hotlineNumber);
sdkPrintStr(printBuffer, 1, 1, 0, 3);
sdkPrintStart();
return;
}