v4.6.0
This commit is contained in:
207
hailort/common/os/windows/ethernet_utils.cpp
Normal file
207
hailort/common/os/windows/ethernet_utils.cpp
Normal 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 */
|
||||
132
hailort/common/os/windows/filesystem.cpp
Normal file
132
hailort/common/os/windows/filesystem.cpp
Normal 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 */
|
||||
25
hailort/common/os/windows/process.cpp
Normal file
25
hailort/common/os/windows/process.cpp
Normal 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 */
|
||||
288
hailort/common/os/windows/socket.cpp
Normal file
288
hailort/common/os/windows/socket.cpp
Normal 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 */
|
||||
63
hailort/common/os/windows/string_conversion.cpp
Normal file
63
hailort/common/os/windows/string_conversion.cpp
Normal 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 */
|
||||
34
hailort/common/os/windows/string_conversion.hpp
Normal file
34
hailort/common/os/windows/string_conversion.hpp
Normal 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_ */
|
||||
Reference in New Issue
Block a user