- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
175 lines
4.9 KiB
C++
175 lines
4.9 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright (C) 2022-2023 chargebyte GmbH
|
|
// Copyright (C) 2022-2023 Contributors to EVerest
|
|
#include "tools.hpp"
|
|
#include "log.hpp"
|
|
#include <arpa/inet.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <ifaddrs.h>
|
|
#include <iomanip>
|
|
#include <math.h>
|
|
#include <sstream>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
ssize_t safe_read(int fd, void* buf, size_t count) {
|
|
for (;;) {
|
|
ssize_t result = read(fd, buf, count);
|
|
|
|
if (result >= 0)
|
|
return result;
|
|
else if (errno == EINTR)
|
|
continue;
|
|
else
|
|
return result;
|
|
}
|
|
}
|
|
|
|
const char* choose_first_ipv6_interface() {
|
|
struct ifaddrs *ifaddr, *ifa;
|
|
char buffer[INET6_ADDRSTRLEN];
|
|
|
|
if (getifaddrs(&ifaddr) == -1)
|
|
return NULL;
|
|
|
|
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
if (!ifa->ifa_addr)
|
|
continue;
|
|
|
|
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
|
inet_ntop(AF_INET6, &ifa->ifa_addr->sa_data, buffer, sizeof(buffer));
|
|
if (strstr(buffer, "fe80") != NULL) {
|
|
return ifa->ifa_name;
|
|
}
|
|
}
|
|
}
|
|
dlog(DLOG_LEVEL_ERROR, "No necessary IPv6 link-local address was found!");
|
|
return NULL;
|
|
}
|
|
|
|
int get_interface_ipv6_address(const char* if_name, enum Addr6Type type, struct sockaddr_in6* addr) {
|
|
struct ifaddrs *ifaddr, *ifa;
|
|
int rv = -1;
|
|
|
|
if (getifaddrs(&ifaddr) == -1)
|
|
return -1;
|
|
|
|
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
if (!ifa->ifa_addr)
|
|
continue;
|
|
|
|
if (ifa->ifa_addr->sa_family != AF_INET6)
|
|
continue;
|
|
|
|
if (strcmp(ifa->ifa_name, if_name) != 0)
|
|
continue;
|
|
|
|
/* on Linux the scope_id is interface index for link-local addresses */
|
|
switch (type) {
|
|
case ADDR6_TYPE_GLOBAL: /* no link-local address requested */
|
|
if ((reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr))->sin6_scope_id != 0)
|
|
continue;
|
|
break;
|
|
|
|
case ADDR6_TYPE_LINKLOCAL: /* link-local address requested */
|
|
if ((reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr))->sin6_scope_id == 0)
|
|
continue;
|
|
break;
|
|
|
|
default: /* any address of the interface requested */
|
|
/* use first found */
|
|
break;
|
|
}
|
|
|
|
memcpy(addr, ifa->ifa_addr, sizeof(*addr));
|
|
|
|
rv = 0;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
freeifaddrs(ifaddr);
|
|
return rv;
|
|
}
|
|
|
|
#define NSEC_PER_SEC 1000000000L
|
|
|
|
void set_normalized_timespec(struct timespec* ts, time_t sec, int64_t nsec) {
|
|
while (nsec >= NSEC_PER_SEC) {
|
|
nsec -= NSEC_PER_SEC;
|
|
++sec;
|
|
}
|
|
while (nsec < 0) {
|
|
nsec += NSEC_PER_SEC;
|
|
--sec;
|
|
}
|
|
ts->tv_sec = sec;
|
|
ts->tv_nsec = nsec;
|
|
}
|
|
|
|
struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) {
|
|
struct timespec ts_delta;
|
|
|
|
set_normalized_timespec(&ts_delta, lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec);
|
|
|
|
return ts_delta;
|
|
}
|
|
|
|
long long timespec_to_ms(struct timespec ts) {
|
|
return ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
|
|
}
|
|
|
|
bool get_dir_filename(char* file_name, uint8_t file_name_len, const char* path, const char* file_name_identifier) {
|
|
|
|
file_name[0] = '\0';
|
|
|
|
if (path == NULL) {
|
|
dlog(DLOG_LEVEL_ERROR, "Invalid file path");
|
|
return false;
|
|
}
|
|
DIR* d = opendir(path); // open the path
|
|
|
|
if (d == NULL) {
|
|
dlog(DLOG_LEVEL_ERROR, "Unable to open file path %s", path);
|
|
return false;
|
|
}
|
|
struct dirent* dir; // for the directory entries
|
|
uint8_t file_name_identifier_len = std::string(file_name_identifier).size();
|
|
while ((dir = readdir(d)) != NULL) {
|
|
if (dir->d_type != DT_DIR) {
|
|
/* if the type is not directory*/
|
|
if ((std::string(dir->d_name).size() > (file_name_identifier_len)) && /* Plus one for the numbering */
|
|
(strncmp(file_name_identifier, dir->d_name, file_name_identifier_len) == 0) &&
|
|
(file_name_len > std::string(dir->d_name).size())) {
|
|
strncpy(file_name, dir->d_name, std::string(dir->d_name).size() + 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
closedir(d);
|
|
|
|
return (file_name[0] != '\0');
|
|
}
|
|
|
|
types::iso15118::HashAlgorithm convert_to_hash_algorithm(const types::evse_security::HashAlgorithm hash_algorithm) {
|
|
switch (hash_algorithm) {
|
|
case types::evse_security::HashAlgorithm::SHA256:
|
|
return types::iso15118::HashAlgorithm::SHA256;
|
|
case types::evse_security::HashAlgorithm::SHA384:
|
|
return types::iso15118::HashAlgorithm::SHA384;
|
|
case types::evse_security::HashAlgorithm::SHA512:
|
|
return types::iso15118::HashAlgorithm::SHA512;
|
|
default:
|
|
throw std::runtime_error(
|
|
"Could not convert types::evse_security::HashAlgorithm to types::iso15118::HashAlgorithm");
|
|
}
|
|
}
|