Разбор HTTP-данных в C с использованием MCU - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь проанализировать данные, полученные из запроса GET / POST, используя C в MCU-проекте. Я должен сказать заранее, что я некоторое время не работал с c и c ++, поэтому любые предложения приветствуются.

Итак, данные, поступающие в MCU, имеют следующую разметку:

HTTP/1.1
Authorization: Basic blablah
Content-Type: application/json
{
redLedBrightness:50,
redLedIsOn:true,
greenLedBrightness:70,
greenLedIsOn:false,
}

где начало конца строк задается соответственно \r и \n. Мой подход подразумевал построчную обработку и поиск соответствующего ключа (например, Authorization или redLedBrightness) и его значения (например, blahblah или 50). Я написал следующий код, который, казалось, работал нормально в компиляторе, который я использовал, но не в MCU.

Одна из проблем, кажется, заключается в утверждении *tempInDataP = *index;, поскольку MCU перестает зависать, если я закомментирую его. Конечно, мне нужна эта строка, но я не могу понять, где проблема (ы). Я подозреваю, что компилятор, который я использую, не показывает все ошибки.

Вот адаптация кода:

#include <iostream>
#include <string>
#include <cstring>
#define IN_DATA_SIZE 100
#define TEMP_IN_DATA_SIZE 10
using namespace std;
char mock[] = "Authentication:YERL90,\r\nredLedBri:400,\r\nredLedOn:true\r\n";
char * mockP = mock;

char inData[IN_DATA_SIZE];
char * inDataP = inData;
char tempInData[TEMP_IN_DATA_SIZE];
char * tempInDataP = tempInData;
const char * auth = "YERL90";
bool isAuthenticated = false;

void printBuffer(char * buf) {
    for (char *p = buf; *p; p++) {
        cout << *p;
    }
}

void resetBuffer(char * buf, int _size)
{
  memset(buf, 0, _size);
}

/**
 * Returns true if keyWord exists and update the variable tempInData
 * with the response / value
 */
bool parseResponse(char * res, const char * keyWord, int dataShift ) {
  cout << "\nParsing:" << res << endl;
  char * index;

  // Reset temp in data buffer and its pointer
  resetBuffer(tempInData, TEMP_IN_DATA_SIZE);
  tempInDataP = &tempInData[0];

  // Search for a member /keyword inside the response
  index = strstr(res, keyWord);

  if (index) {
      // Keyword exists in the response
      // Move the index to the beginning of the value (key:value)
    index = index + strlen(keyWord) + dataShift;
    while ((*index != '\r') && (*index != ',')) {
      *tempInDataP = *index;
      tempInDataP++;
      index++;
    }

    // Terminate the string with a null
    *tempInDataP = '\0';
    return true;
  } else {
      cout << "-bul" << endl;
      //Object was not found
    return false;
  }
}


bool checkAuth(const char * _auth) {
    if (strcmp (auth, _auth) == 0) 
        return true;
     else 
        return false;
}


int main()
{
    while(*mockP) {
    // Simulating, reading data from the channel
    *inDataP=*mockP;
    //Parsing line by line
    if (*inDataP == '\n') {
        //Check for authentication if not done yet
        if(!isAuthenticated) {
            cout << "Authenticating ..." << endl;
            if(parseResponse(inData, "Authentication", 1)) {
                cout << "Key exists ..." << endl;
                if(checkAuth(tempInData)) {
                    cout << "Correct Password" << endl;
                    isAuthenticated = true;
                } else {
                  cout << "Password Invalid" << endl;
                  // Prepare headers
                  // Send response with unauthorized access
                  // stop connection
                  break;
                } 
            } else {
                cout << "Data not found" << endl;
            }
        } else {
            // User is logged in
            cout << "User is logged in" << endl;
            if(parseResponse(inData, "redLedBri", 1)) {
               cout << "Data exists:" << tempInData << endl;
               // update local variables
            } else {
                cout << "Data not found" << endl;
            }

        }
        resetBuffer(inData, IN_DATA_SIZE);
        inDataP = &inData[0];
    }  
    else {
       inDataP++;
    }
    mockP++;
    } 

    //close connection and log the user out

   return 0;
}

Я открыт для других альтернатив, поскольку эта реализация кажется немного громоздкий в зависимости от файла JSON, отправляемого в MCU.

1 Ответ

0 голосов
/ 15 апреля 2020

Я вижу потенциальные переполнения буфера. Вы слишком доверяете своему вкладу. Вы предполагаете, что он будет заканчиваться символами '\ r' или ',', а если этого не произойдет, то вы выйдете за границы вашего массива (ов) и получите доступ к произвольной памяти.

Как минимум, передавайте максимальную длину с каждым указателем массива и проверяйте в каждой итерации l oop, что вы НИКОГДА не обращаетесь к элементу за последним адресом массива.

...