This commit is contained in:
HailoRT-Automation
2022-03-29 19:08:05 +03:00
commit dd37bf9936
370 changed files with 80735 additions and 0 deletions

View File

@@ -0,0 +1,207 @@
#include "common/ethernet_utils.hpp"
#include "common/socket.hpp"
#include "common/os/windows/string_conversion.hpp"
#include "hailo/hailort.h"
#include "common/logger_macros.hpp"
#include "hailo/buffer.hpp"
#include <array>
#include <iphlpapi.h>
namespace hailort
{
NetworkInterface::NetworkInterface(uint32_t index, const std::string& name, const std::string& friendly_name, const std::string& ip) :
m_index(index),
m_name(name),
m_friendly_name(friendly_name),
m_ip(ip)
{}
uint32_t NetworkInterface::index() const
{
return m_index;
}
std::string NetworkInterface::name() const
{
return m_name;
}
std::string NetworkInterface::friendly_name() const
{
return m_friendly_name;
}
std::string NetworkInterface::ip() const
{
return m_ip;
}
Expected<NetworkInterfaces> NetworkInterface::get_all_interfaces()
{
static const ULONG IPV4 = AF_INET;
static const ULONG UNICAST_ONLY = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
static const PVOID RESERVED = nullptr;
static const PIP_ADAPTER_ADDRESSES NO_INTERFACE_INFO = nullptr;
ULONG required_size = 0;
ULONG ret_value = GetAdaptersAddresses(IPV4, UNICAST_ONLY, RESERVED, NO_INTERFACE_INFO, &required_size);
if (ret_value != ERROR_BUFFER_OVERFLOW) {
LOGGER__ERROR("Failed calculating necessary size for IP_ADAPTER_ADDRESSES. "
"Expected ret_value=ERROR_BUFFER_OVERFLOW, received={}", ret_value);
return make_unexpected(HAILO_UNEXPECTED_INTERFACE_INFO_FAILURE);
}
auto interface_info_buffer = Buffer::create(required_size, 0);
CHECK_EXPECTED(interface_info_buffer);
ret_value = GetAdaptersAddresses(IPV4, UNICAST_ONLY, RESERVED,
interface_info_buffer->as_pointer<IP_ADAPTER_ADDRESSES>(), &required_size);
if (ret_value == ERROR_NO_DATA) {
LOGGER__ERROR("No IPv4 interfaces found");
return make_unexpected(HAILO_NO_IPV4_INTERFACES_FOUND);
} else if (ret_value != NO_ERROR) {
LOGGER__ERROR("GetInterfaceInfo failed with error: {}", ret_value);
return make_unexpected(HAILO_UNEXPECTED_INTERFACE_INFO_FAILURE);
}
NetworkInterfaces interfaces;
PIP_ADAPTER_ADDRESSES interface_info = interface_info_buffer->as_pointer<IP_ADAPTER_ADDRESSES>();
while (interface_info != nullptr) {
PIP_ADAPTER_UNICAST_ADDRESS first_unicast_address = interface_info->FirstUnicastAddress;
// TODO: keep a vector of all addresses
if (first_unicast_address == nullptr) {
LOGGER__DEBUG("first_unicast_address is null. Skipping.");
continue;
}
const auto address_struct = first_unicast_address->Address.lpSockaddr;
if ((address_struct == nullptr) || (address_struct->sa_family != AF_INET)) {
LOGGER__DEBUG("Unicast address is invalid. Skipping.");
continue;
}
auto ip = Buffer::create(IPV4_STRING_MAX_LENGTH);
CHECK_EXPECTED(ip);
const auto result = Socket::ntop(AF_INET, &(reinterpret_cast<sockaddr_in *>(address_struct)->sin_addr),
ip->as_pointer<char>(), EthernetUtils::MAX_INTERFACE_SIZE);
if (result != HAILO_SUCCESS) {
LOGGER__DEBUG("Failed converting unicast address to string (result={}). Skipping.", result);
continue;
}
const auto friendly_name_ansi = StringConverter::utf16_to_ansi(interface_info->FriendlyName);
if (!friendly_name_ansi.has_value()) {
LOGGER__DEBUG("Failed converting the interface's friendly_name to ansi (result={}). Skipping.",
friendly_name_ansi.status());
continue;
}
interfaces.emplace_back(interface_info->IfIndex, interface_info->AdapterName,
friendly_name_ansi.value(), ip->to_string());
interface_info = interface_info->Next;
}
return interfaces;
}
ArpTable::ArpTable(const std::unordered_map<uint32_t, MacAddress>& table) :
m_table(table)
{}
Expected<MacAddress> ArpTable::get_mac_address(uint32_t ip) const
{
auto search = m_table.find(ip);
if (search == m_table.end()) {
return make_unexpected(HAILO_MAC_ADDRESS_NOT_FOUND);
}
return Expected<MacAddress>(m_table.at(ip));
}
Expected<ArpTable> ArpTable::create(uint32_t interface_index)
{
static const PMIB_IPNETTABLE NO_NETTABLE = nullptr;
static const BOOL SORTED = true;
ULONG required_size = 0;
ULONG ret_value = GetIpNetTable(NO_NETTABLE, &required_size, SORTED);
if (ret_value != ERROR_INSUFFICIENT_BUFFER) {
LOGGER__ERROR("Failed calculating necessary size for MIB_IPNETTABLE. Expected ret_value=ERROR_INSUFFICIENT_BUFFER, received={}", ret_value);
return make_unexpected(HAILO_UNEXPECTED_ARP_TABLE_FAILURE);
}
auto ip_net_table_buffer = Buffer::create(required_size, 0);
CHECK_EXPECTED(ip_net_table_buffer);
ret_value = GetIpNetTable(ip_net_table_buffer->as_pointer<MIB_IPNETTABLE>(), &required_size, SORTED);
if (ret_value == ERROR_NO_DATA) {
LOGGER__ERROR("No IPv4 interfaces found");
return make_unexpected(HAILO_NO_IPV4_INTERFACES_FOUND);
} else if (ret_value != NO_ERROR) {
LOGGER__ERROR("GetIpNetTable failed with error: {}", ret_value);
return make_unexpected(HAILO_UNEXPECTED_ARP_TABLE_FAILURE);
}
std::unordered_map<uint32_t, MacAddress> result;
const PMIB_IPNETTABLE ip_net_table = ip_net_table_buffer->as_pointer<MIB_IPNETTABLE>();
for (uint32_t i = 0; i < ip_net_table->dwNumEntries; i++) {
if (ip_net_table->table[i].dwIndex != interface_index) {
continue;
}
if (ip_net_table->table[i].dwPhysAddrLen != MacAddressSize) {
continue;
}
const uint32_t ip = ip_net_table->table[i].dwAddr;
MacAddress mac{};
memcpy(mac.data(), ip_net_table->table[i].bPhysAddr, MacAddressSize);
result[ip] = mac;
}
return result;
}
hailo_status EthernetUtils::get_interface_from_board_ip(const char *board_ip, char *interface_name, size_t interface_name_length)
{
CHECK_ARG_NOT_NULL(interface_name);
CHECK_ARG_NOT_NULL(board_ip);
auto network_interfaces = NetworkInterface::get_all_interfaces();
CHECK_EXPECTED_AS_STATUS(network_interfaces);
struct in_addr board_ip_struct{};
auto status = Socket::pton(AF_INET, board_ip, &board_ip_struct);
CHECK_SUCCESS(status);
for (const auto& network_interface : network_interfaces.value()) {
auto arp_table = ArpTable::create(network_interface.index());
CHECK_EXPECTED_AS_STATUS(arp_table);
const auto mac_address = arp_table->get_mac_address(static_cast<uint32_t>(board_ip_struct.S_un.S_addr));
if (mac_address) {
(void)strncpy(interface_name, network_interface.friendly_name().c_str(), interface_name_length);
return HAILO_SUCCESS;
}
}
return HAILO_ETH_INTERFACE_NOT_FOUND;
}
hailo_status EthernetUtils::get_ip_from_interface(const char *interface_name, char *ip, size_t ip_length)
{
CHECK_ARG_NOT_NULL(interface_name);
CHECK_ARG_NOT_NULL(ip);
auto network_interfaces = NetworkInterface::get_all_interfaces();
CHECK_EXPECTED_AS_STATUS(network_interfaces);
for (const auto& network_interface : network_interfaces.value()) {
if (network_interface.friendly_name() == interface_name) {
(void)strncpy(ip, network_interface.ip().c_str(), ip_length);
return HAILO_SUCCESS;
}
}
return HAILO_ETH_INTERFACE_NOT_FOUND;
}
} /* namespace hailort */

View File

@@ -0,0 +1,132 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file filesystem.cpp
* @brief Filesystem wrapper for Windows
**/
#include "common/filesystem.hpp"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include <shlwapi.h>
namespace hailort
{
const char *Filesystem::SEPARATOR = "\\";
Expected<Filesystem::FindFile> Filesystem::FindFile::create(const std::string &dir_path)
{
static const char *DIR_WALK_WILD_CARD = "*";
const std::string dir_path_with_sep = has_suffix(dir_path, SEPARATOR) ? dir_path + DIR_WALK_WILD_CARD :
dir_path + SEPARATOR + DIR_WALK_WILD_CARD;
WIN32_FIND_DATAA find_data{};
auto find_handle = FindFirstFileA(dir_path_with_sep.c_str(), &find_data);
if (INVALID_HANDLE_VALUE == find_handle) {
const auto last_error = GetLastError();
if (last_error == ERROR_FILE_NOT_FOUND) {
LOGGER__ERROR("No matching files could be found \"{}\"", dir_path_with_sep.c_str());
} else {
LOGGER__ERROR("FindFirstFileA(\"{}\") failed with LE={}", dir_path_with_sep.c_str(), last_error);
}
return make_unexpected(HAILO_FILE_OPERATION_FAILURE);
}
// Note: find_data will be copied into the m_find_data member (it doesn't contain pointers)
return std::move(FindFile(find_handle, find_data));
}
Filesystem::FindFile::FindFile(HANDLE find_hadle, const WIN32_FIND_DATAA &find_data) :
m_find_handle(find_hadle),
m_find_data(find_data)
{}
Filesystem::FindFile::~FindFile()
{
if (INVALID_HANDLE_VALUE != m_find_handle) {
const auto result = FindClose(m_find_handle);
if (0 == result) {
LOGGER__ERROR("FindClose on handle={} failed with LE={}", m_find_handle, GetLastError());
}
}
}
Filesystem::FindFile::FindFile(FindFile &&other) :
m_find_handle(std::exchange(other.m_find_handle, INVALID_HANDLE_VALUE)),
m_find_data(other.m_find_data)
{}
Filesystem::FileInfo Filesystem::FindFile::get_cur_file_info()
{
return {m_find_data.cFileName, m_find_data.dwFileAttributes};
}
hailo_status Filesystem::FindFile::next_file()
{
const auto result = FindNextFileA(m_find_handle, &m_find_data);
if (result) {
return HAILO_SUCCESS;
}
const auto last_error = GetLastError();
if (last_error == ERROR_NO_MORE_FILES) {
// No more files
return HAILO_INVALID_OPERATION;
}
LOGGER__ERROR("FindNextFileA() failed with LE={}", last_error);
return HAILO_FILE_OPERATION_FAILURE;
}
bool Filesystem::is_regular_or_readonly_file(DWORD attrs)
{
return (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
Expected<std::vector<std::string>> Filesystem::get_files_in_dir_flat(const std::string &dir_path)
{
const std::string dir_path_with_sep = has_suffix(dir_path, SEPARATOR) ? dir_path : dir_path + SEPARATOR;
auto dir = FindFile::create(dir_path_with_sep);
CHECK_EXPECTED(dir);
std::vector<std::string> files;
auto file_info = dir->get_cur_file_info();
if (is_regular_or_readonly_file(file_info.attrs)) {
files.emplace_back(file_info.path);
}
hailo_status status = HAILO_UNINITIALIZED;
while (true) {
status = dir->next_file();
if (HAILO_INVALID_OPERATION == status) {
// We're done
break;
}
if (HAILO_SUCCESS != status) {
// Best effort
LOGGER__ERROR("next_file failed with status {}; skipping", status);
continue;
}
file_info = dir->get_cur_file_info();
if (is_regular_or_readonly_file(file_info.attrs)) {
files.emplace_back(dir_path_with_sep + file_info.path);
}
}
return files;
}
Expected<bool> Filesystem::is_directory(const std::string &path)
{
if (path.length() > MAX_PATH) {
LOGGER__ERROR("path is too long (MAX_PATH={}, received length={}", MAX_PATH, path.length());
return make_unexpected(HAILO_INVALID_ARGUMENT);
}
return PathIsDirectoryA(path.c_str());
}
} /* namespace hailort */

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file process.cpp
* @brief Process wrapper for Windows
**/
#include "common/process.hpp"
#include "hailo/hailort.h"
#include "common/utils.hpp"
namespace hailort
{
Expected<std::pair<int32_t, std::string>> Process::create_and_wait_for_output(const std::string &command_line, uint32_t max_output_size)
{
// TODO: Add windows impl (HRT-2510)
command_line;
max_output_size;
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
} /* namespace hailort */

View File

@@ -0,0 +1,288 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file socket.cpp
* @brief Socket wrapper for Windows
**/
#include "common/socket.hpp"
#include <array>
namespace hailort
{
#define WSA_VERSION MAKEWORD(2, 2)
hailo_status Socket::SocketModuleWrapper::init_module()
{
uint16_t wsa_version = WSA_VERSION;
WSADATA wsa_data{};
int wsa_rt = SOCKET_ERROR;
wsa_rt = WSAStartup(wsa_version, &wsa_data);
CHECK(0 == wsa_rt, HAILO_ETH_FAILURE, "WSAStartup failed. rt={}", wsa_rt);
return HAILO_SUCCESS;
}
hailo_status Socket::SocketModuleWrapper::free_module()
{
int wsa_rt = SOCKET_ERROR;
wsa_rt = WSACleanup();
CHECK(0 == wsa_rt, HAILO_ETH_FAILURE, "WSACleanup failed. LE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
Expected<Socket> Socket::create(int af, int type, int protocol)
{
auto module_wrapper = SocketModuleWrapper::create();
CHECK_EXPECTED(module_wrapper);
auto socket_fd = create_socket_fd(af, type, protocol);
CHECK_EXPECTED(socket_fd);
auto obj = Socket(module_wrapper.release(), socket_fd.release());
return std::move(obj);
}
Socket::Socket(SocketModuleWrapper &&module_wrapper, const socket_t socket_fd) :
m_module_wrapper(std::move(module_wrapper)), m_socket_fd(socket_fd)
{
}
Socket::~Socket()
{
auto status = close_socket_fd();
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to free socket fd with status {:X}");
}
}
Expected<socket_t> Socket::create_socket_fd(int af, int type, int protocol)
{
socket_t local_socket = INVALID_SOCKET;
local_socket = socket(af, type, protocol);
CHECK_VALID_SOCKET_AS_EXPECTED(local_socket);
return local_socket;
}
hailo_status Socket::abort()
{
return HAILO_NOT_IMPLEMENTED;
}
hailo_status Socket::close_socket_fd()
{
if (INVALID_SOCKET != m_socket_fd) {
int socket_rc = closesocket(m_socket_fd);
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed to close socket. WSALE={}", WSAGetLastError());
}
return HAILO_SUCCESS;
}
hailo_status Socket::socket_bind(const sockaddr *addr, socklen_t len)
{
int socket_rc = SOCKET_ERROR;
CHECK_ARG_NOT_NULL(addr);
socket_rc = bind(m_socket_fd, addr, len);
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed to bind socket. WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::get_sock_name(sockaddr *addr, socklen_t *len)
{
int socket_rc = SOCKET_ERROR;
CHECK_ARG_NOT_NULL(addr);
CHECK_ARG_NOT_NULL(len);
socket_rc = getsockname(m_socket_fd, addr, len);
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed getsockname. WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::ntop(int af, const void *src, char *dst, socklen_t size)
{
CHECK_ARG_NOT_NULL(src);
CHECK_ARG_NOT_NULL(dst);
auto module_wrapper = SocketModuleWrapper::create();
CHECK_EXPECTED_AS_STATUS(module_wrapper);
const char *inet_result = inet_ntop(af, src, dst, size);
CHECK(nullptr != inet_result, HAILO_ETH_FAILURE, "Failed inet_ntop. WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::pton(int af, const char *src, void *dst)
{
int inet_result = SOCKET_ERROR;
CHECK_ARG_NOT_NULL(src);
CHECK_ARG_NOT_NULL(dst);
auto module_wrapper = SocketModuleWrapper::create();
CHECK_EXPECTED_AS_STATUS(module_wrapper);
inet_result = inet_pton(af, src, dst);
CHECK(1 == inet_result, HAILO_ETH_FAILURE, "Failed inet_pton. WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::set_recv_buffer_size_max()
{
int socket_rc = SOCKET_ERROR;
// TOOD: MAX_SIZE?? https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
const int MAX_RECV_BUFFER_SIZE = 52428800;
socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_RCVBUF,
reinterpret_cast<const char*>(&MAX_RECV_BUFFER_SIZE), sizeof(MAX_RECV_BUFFER_SIZE));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed setsockopt(SOL_SOCKET, SO_RCVBUF). WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::set_timeout(const std::chrono::milliseconds timeout_ms, timeval_t *timeout)
{
int socket_rc = SOCKET_ERROR;
auto timeout_value = static_cast<uint32_t>(timeout_ms.count());
/* Validate arguments */
CHECK_ARG_NOT_NULL(timeout);
// From https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options (SO_RCVTIMEO):
// If the socket is created using the WSASocket function, then the dwFlags parameter must have the
// WSA_FLAG_OVERLAPPED attribute set for the timeout to function properly. Otherwise the timeout never takes effect.
socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<const char*>(&timeout_value), sizeof(timeout_value));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed setsockopt(SOL_SOCKET, SO_RCVTIMEO). WSALE={}", WSAGetLastError());
socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_SNDTIMEO,
reinterpret_cast<const char*>(&timeout_value), sizeof(timeout_value));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed setsockopt(SOL_SOCKET, SO_SNDTIMEO). WSALE={}", WSAGetLastError());
timeout->tv_sec = timeout_value / MILLISECONDS_IN_SECOND;
timeout->tv_usec = (timeout_value % MILLISECONDS_IN_SECOND) * MICROSECONDS_IN_MILLISECOND;
return HAILO_SUCCESS;
}
hailo_status Socket::enable_broadcast()
{
int socket_rc = SOCKET_ERROR;
int enable_broadcast = 1;
socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_BROADCAST,
reinterpret_cast<const char*>(&enable_broadcast), sizeof(enable_broadcast));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed setsockopt(SOL_SOCKET, SO_BROADCAST). WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::send_to(const uint8_t *src_buffer, size_t src_buffer_size, int flags,
const sockaddr *dest_addr, socklen_t dest_addr_size, size_t *bytes_sent)
{
int number_of_sent_bytes = SOCKET_ERROR;
/* Validate arguments */
CHECK_ARG_NOT_NULL(src_buffer);
CHECK_ARG_NOT_NULL(dest_addr);
CHECK_ARG_NOT_NULL(bytes_sent);
number_of_sent_bytes = sendto(m_socket_fd, reinterpret_cast<const char*>(src_buffer),
static_cast<int>(src_buffer_size), flags, dest_addr, dest_addr_size);
if (SOCKET_ERROR == number_of_sent_bytes) {
const int wsale = WSAGetLastError();
if (WSAETIMEDOUT == errno) {
LOGGER__ERROR("Udp send timeout");
return HAILO_TIMEOUT;
} else {
LOGGER__ERROR("Udp failed to send data, WSALE={}.", wsale);
return HAILO_ETH_SEND_FAILURE;
}
}
*bytes_sent = (size_t)number_of_sent_bytes;
return HAILO_SUCCESS;
}
hailo_status Socket::recv_from(uint8_t *dest_buffer, size_t dest_buffer_size, int flags,
sockaddr *src_addr, socklen_t src_addr_size, size_t *bytes_recieved, bool log_timeouts_in_debug)
{
int number_of_received_bytes = SOCKET_ERROR;
socklen_t result_src_addr_size = src_addr_size;
/* Validate arguments */
CHECK_ARG_NOT_NULL(dest_buffer);
CHECK_ARG_NOT_NULL(src_addr);
CHECK_ARG_NOT_NULL(bytes_recieved);
number_of_received_bytes = recvfrom(m_socket_fd, reinterpret_cast<char*>(dest_buffer),
static_cast<int>(dest_buffer_size), flags, src_addr, &result_src_addr_size);
if (SOCKET_ERROR == number_of_received_bytes) {
const int wsale = WSAGetLastError();
if (WSAETIMEDOUT == wsale) {
if (log_timeouts_in_debug) {
LOGGER__DEBUG("Udp recvfrom failed with timeout");
} else {
LOGGER__ERROR("Udp recvfrom failed with timeout");
}
return HAILO_TIMEOUT;
} else {
LOGGER__ERROR("Udp failed to recv data. WSALE={}.", wsale);
return HAILO_ETH_RECV_FAILURE;
}
}
*bytes_recieved = static_cast<size_t>(number_of_received_bytes);
return HAILO_SUCCESS;
}
hailo_status Socket::has_data(sockaddr *src_addr, socklen_t src_addr_size, bool log_timeouts_in_debug)
{
int number_of_received_bytes = SOCKET_ERROR;
socklen_t result_src_addr_size = src_addr_size;
static const size_t DEST_BUFFER_SIZE = 1;
std::array<char, DEST_BUFFER_SIZE> dest_buffer{};
/* Validate arguments */
CHECK_ARG_NOT_NULL(src_addr);
static const int NO_FLAGS = 0;
number_of_received_bytes = recvfrom(m_socket_fd, dest_buffer.data(), static_cast<int>(dest_buffer.size()), NO_FLAGS,
src_addr, &result_src_addr_size);
if (SOCKET_ERROR == number_of_received_bytes) {
const int wsale = WSAGetLastError();
if (WSAETIMEDOUT == wsale) {
if (log_timeouts_in_debug) {
LOGGER__DEBUG("Udp recvfrom failed with timeout");
} else {
LOGGER__ERROR("Udp recvfrom failed with timeout");
}
return HAILO_TIMEOUT;
}
// The message may be bigger than DEST_BUFFER_SIZE bytes, leading to WSAEMSGSIZE. This is ok
if (WSAEMSGSIZE != wsale) {
LOGGER__ERROR("Udp failed to recv data. WSALE={}.", wsale);
return HAILO_ETH_RECV_FAILURE;
}
}
return HAILO_SUCCESS;
}
} /* namespace hailort */

View File

@@ -0,0 +1,63 @@
#include <vector>
#include "common/os/windows/string_conversion.hpp"
#include "common/utils.hpp"
namespace hailort
{
Expected<std::wstring> StringConverter::ansi_to_utf16(const std::string& ansi_string)
{
static const UINT ANSI_CODE_PAGE = CP_ACP;
static const DWORD FAIL_ON_INVALID_CHARS = MB_ERR_INVALID_CHARS;
static const int CALCULATE_INPUT_LENGTH = -1;
static const LPWSTR NO_WIDE_CHAR_BUFFER = nullptr;
static const int CALCULATE_RESULT_LENGTH = 0;
const int required_length = MultiByteToWideChar(ANSI_CODE_PAGE, FAIL_ON_INVALID_CHARS, ansi_string.c_str(),
CALCULATE_INPUT_LENGTH, NO_WIDE_CHAR_BUFFER, CALCULATE_RESULT_LENGTH);
if (0 == required_length) {
LOGGER__ERROR("Failed calculating necessary length for '{}' as unicode string. LE={}", ansi_string, GetLastError());
return make_unexpected(HAILO_ANSI_TO_UTF16_CONVERSION_FAILED );
}
std::vector<wchar_t> result_buffer(required_length, L'\0');
const int allocated_length = MultiByteToWideChar(ANSI_CODE_PAGE, FAIL_ON_INVALID_CHARS, ansi_string.c_str(),
CALCULATE_INPUT_LENGTH, result_buffer.data(), required_length);
if (0 == allocated_length || allocated_length != required_length) {
LOGGER__ERROR("Failed converting '{}' to unicode string. LE={}", ansi_string, GetLastError());
return make_unexpected(HAILO_ANSI_TO_UTF16_CONVERSION_FAILED );
}
// result_buffer includes the terminating null
return std::wstring(result_buffer.data());
}
Expected<std::string> StringConverter::utf16_to_ansi(const std::wstring& utf16_string)
{
static const UINT ANSI_CODE_PAGE = CP_ACP;
static const DWORD NO_FLAGS = 0;
static const int CALCULATE_INPUT_LENGTH = -1;
static const LPSTR NO_UTF8_BUFFER = nullptr;
static const int CALCULATE_RESULT_LENGTH = 0;
static const LPCCH USE_SYSTEM_DEFAULT_CHAR = nullptr;
static const LPBOOL NO_CUSTOM_DEFAULT_CHAR = nullptr;
const int required_length = WideCharToMultiByte(ANSI_CODE_PAGE, NO_FLAGS, utf16_string.c_str(),
CALCULATE_INPUT_LENGTH, NO_UTF8_BUFFER, CALCULATE_RESULT_LENGTH, USE_SYSTEM_DEFAULT_CHAR, NO_CUSTOM_DEFAULT_CHAR);
if (0 == required_length) {
LOGGER__ERROR("Failed calculating necessary length for utf16_string as ansi string. LE={}", GetLastError());
return make_unexpected(HAILO_UTF16_TO_ANSI_CONVERSION_FAILED);
}
std::vector<char> result_buffer(required_length, '\0');
const int allocated_length = WideCharToMultiByte(ANSI_CODE_PAGE, NO_FLAGS, utf16_string.c_str(),
CALCULATE_INPUT_LENGTH, result_buffer.data(), required_length, USE_SYSTEM_DEFAULT_CHAR, NO_CUSTOM_DEFAULT_CHAR);
if (0 == allocated_length || allocated_length != required_length) {
LOGGER__ERROR("Failed converting utf16_string to ansi string. LE={}", GetLastError());
return make_unexpected(HAILO_UTF16_TO_ANSI_CONVERSION_FAILED);
}
// result_buffer includes the terminating null
return std::string(result_buffer.data());
}
} /* namespace hailort */

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file string_conversion.hpp
* @brief Safe string encoding conversions.
**/
#ifndef _OS_STRING_CONVERSION_HPP_
#define _OS_STRING_CONVERSION_HPP_
#include <string>
#include <hailo/platform.h>
#include <hailo/hailort.h>
#include "hailo/expected.hpp"
namespace hailort
{
class StringConverter final
{
public:
StringConverter() = delete;
static Expected<std::wstring> ansi_to_utf16(const std::string& ansi_string);
static Expected<std::string> utf16_to_ansi(const std::wstring& utf16_string);
};
} /* namespace hailort */
#endif /* _OS_STRING_CONVERSION_HPP_ */