123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #include <sstream>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <ifaddrs.h>
- #include <curl/curl.h>
- #include <fstream>
- #include "utils.h"
- namespace hm {
- Level gConfLogLevel = Warn;
- std::string gConfFaceRemote = "http://127.0.0.1/", gConfCarRemote = "http://127.0.0.1/", // NOLINT
- gConfLoginUser = "<username here>", gConfLoginPass = "<password here>"; // NOLINT
- unsigned int gConfSearchGap = 60, gConfSearchDuration = 4, gConfServerPort = 8040;
- void ReadConfig(const char *path) {
- std::ifstream file(path);
- if (!file) {
- LogM(Error, "config file \"%s\" open failed.", path);
- } else {
- std::string line, key, value;
- while (std::getline(file, line)) {
- if (line.empty() || line.size() == 1 || line[0] == '#') continue;
- if (splitKeyValue(line, key, value)) {
- if (key == "faceRemote") gConfFaceRemote = value;
- else if (key == "carRemote") gConfCarRemote = value;
- else if (key == "user") gConfLoginUser = value;
- else if (key == "pass") gConfLoginPass = value;
- else if (key == "logLevel") gConfLogLevel = (Level) std::stoi(value);
- else if (key == "searchGap") gConfSearchGap = std::stoi(value);
- else if (key == "searchDuration") gConfSearchDuration = std::stoi(value);
- else if (key == "serverPort") gConfServerPort = std::stoi(value);
- else
- LogM(Warn, "unrecognized config key[%s], value[%s]", key.c_str(), value.c_str());
- }
- }
- }
- Log(
- Trace, "{faceRemote:%s, carRemote:%s, user:%s, pass:%s, logLevel:%d, port:%d, searchGap:%d, searchDuration:%d}",
- gConfFaceRemote.c_str(), gConfCarRemote.c_str(), gConfLoginUser.c_str(), gConfLoginPass.c_str(),
- gConfLogLevel, gConfServerPort, gConfSearchGap, gConfSearchDuration
- );
- }
- const char *logLevelName(const Level &level) {
- switch (level) {
- case Trace:
- return "TRACE";
- case Info:
- return "INFO";
- case Warn:
- return "WARN";
- case Error:
- return "ERROR";
- default:
- return "NULL";
- }
- }
- bool getLogStatus(const Level &level) {
- return gConfLogLevel && level >= gConfLogLevel;
- }
- bool startsWith(const std::string &str, const std::string &start) {
- if (str.length() < start.length()) {
- return false;
- }
- return str.compare(0, start.length(), start) == 0;
- }
- bool endsWith(const std::string &str, const std::string &end) {
- if (str.length() < end.length()) {
- return false;
- }
- return str.compare(str.length() - end.length(), end.length(), end) == 0;
- }
- std::string trim(const std::string &str) {
- unsigned start = 0, end = str.size() - 1;
- while (std::isspace(str[start])) start++;
- while (std::isspace(str[end])) end--;
- return str.substr(start, end - start + 1);
- }
- bool splitKeyValue(const std::string &src, std::string &key, std::string &value) {
- std::stringstream ss(src);
- std::string token;
- if (std::getline(ss, token, '=') && !token.empty()) {
- key = trim(token);
- if (std::getline(ss, token)) {
- value = trim(token);
- return true;
- }
- }
- return false;
- }
- std::vector<std::string> getIpList() {
- std::vector<std::string> ipList;
- struct ifaddrs *ifap, *ifa;
- if (getifaddrs(&ifap) == -1) {
- return ipList;
- }
- for (ifa = ifap; ifa != nullptr; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr == nullptr) {
- continue;
- }
- if (ifa->ifa_addr->sa_family == AF_INET) {
- auto *addr = (struct sockaddr_in *) ifa->ifa_addr;
- char localIP[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &(addr->sin_addr), localIP, INET_ADDRSTRLEN);
- ipList.emplace_back(localIP);
- }
- }
- freeifaddrs(ifap);
- return ipList;
- }
- int imageRead(const std::string &path, char *&buffer) {
- std::ifstream img(path, std::ios::binary);
- img.seekg(0, std::ios::end);
- int size = (int) img.tellg();
- img.seekg(0, std::ios::beg);
- buffer = new char[size];
- img.read(buffer, size);
- return size;
- }
- int imgcpy(char *&dest, const std::string &src) {
- int size = (int) src.size();
- dest = new char[size];
- for (int i = 0; i < size; ++i) dest[i] = src[i];
- return size;
- }
- void imageSave(const std::string &path, char *&start, const int &size) {
- if (size > 0 && start != nullptr) {
- std::ofstream out(path, std::ios::binary);
- if (!out.is_open()) return;
- out.write(start, size);
- out.close();
- }
- }
- void imageSave(const std::string &path, unsigned char *&start, const unsigned int &size) {
- if (size > 0 && start != nullptr) {
- std::ofstream out(path, std::ios::binary);
- if (!out.is_open()) return;
- out.write((char *) start, size);
- out.close();
- }
- }
- time_t toTimestamp(
- const unsigned int &year, const unsigned int &mon, const unsigned int &day,
- const unsigned int &hour, const unsigned int &min, const unsigned int &sec
- ) {
- struct tm info = {
- .tm_sec = (int) sec, .tm_min = (int) min, .tm_hour = (int) hour,
- .tm_mday = (int) day, .tm_mon = (int) mon - 1, .tm_year = (int) year - 1900
- };
- return mktime(&info);
- }
- size_t onPostResponse(void *contents, size_t size, size_t nMem, std::string *output) {
- size_t total_size = size * nMem;
- output->append(static_cast<char *>(contents), total_size);
- return total_size;
- }
- // 22(21+1) errors here, never mind, it's ok anyway.
- void dataUpload(
- const std::string &url, const std::map<std::string, std::string> &data,
- unsigned char *&imgBuf, const unsigned int &bufSize
- ) {
- CURL *curl = curl_easy_init();
- if (!curl) {
- Log(Error, "CURL initialization failed.");
- return;
- }
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- struct curl_httppost *form = nullptr;
- struct curl_httppost *last = nullptr;
- // json data
- for (const auto &it : data) {
- curl_formadd(
- &form, &last, CURLFORM_COPYNAME, it.first.c_str(),
- CURLFORM_COPYCONTENTS, it.second.c_str(), CURLFORM_END
- );
- }
- // image
- curl_formadd(
- &form, &last, CURLFORM_COPYNAME, "image", CURLFORM_BUFFER, "image.jpg",
- CURLFORM_BUFFERPTR, imgBuf, CURLFORM_BUFFERLENGTH, bufSize, CURLFORM_END
- );
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
- // response
- std::string response;
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onPostResponse);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
- CURLcode res = curl_easy_perform(curl);
- if (res == CURLE_OPERATION_TIMEDOUT) {
- Log(Warn, "Connection Timeout");
- } else if (res == CURLE_OK) {
- long code;
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
- if (code == 200) {
- Log(Trace, "upload success with: %s", response.c_str());
- } else {
- Log(Warn, "upload fail with: code[%ld], msg: %s", code, response.c_str());
- }
- } else {
- Log(Error, "HTTP request failed: %s", curl_easy_strerror(res));
- }
- curl_easy_cleanup(curl);
- curl_formfree(form);
- }
- }
|