首页 > 解决方案 > 使用 MCU 在 C 中解析 HTTP 数据

问题描述

我正在尝试在基于 MCU 的项目中使用 C 解析从 GET / POST 请求中获得的数据。我必须提前说,我已经有一段时间没有使用 c 和 c++ 了,所以欢迎任何建议。

因此,到达 MCU 的数据具有以下标记:

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

其中行的结尾分别由\r和给出\n。我的方法需要逐行处理,并搜索相应的键(例如Authorizationor redLedBrightness)及其值(例如blahblahor 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;
}

我对其他替代方案持开放态度,因为根据发送到 MCU 的 JSON 文件,此实现似乎有点麻烦。

标签: c++cnodemcu

解决方案


我看到潜在的缓冲区溢出。你太相信你的意见了。您假设它将以 '\r' 或 ',' 字符结尾,如果不是,那么您将超出数组的边界并访问任意内存。

至少,为每个数组指针传递最大长度,并在每次循环迭代中检查您永远不会访问数组最后地址之外的元素。


推荐阅读