SockOps
This commit is contained in:
@ -250,7 +250,7 @@ namespace IACore
|
|||||||
size_ = static_cast<size_t>(size.QuadPart);
|
size_ = static_cast<size_t>(size.QuadPart);
|
||||||
|
|
||||||
// 3. Create Mapping Object
|
// 3. Create Mapping Object
|
||||||
hMapping_ = ::CreateFileMappingA(hFile_, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
hMapping_ = ::CreateFileMappingA(hFile_, nullptr, PAGE_READWRITE, 0, 0, nullptr);
|
||||||
if (!hMapping_)
|
if (!hMapping_)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
@ -258,7 +258,7 @@ namespace IACore
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. Map View
|
// 4. Map View
|
||||||
data_ = ::MapViewOfFile(hMapping_, FILE_MAP_READ, 0, 0, 0);
|
data_ = ::MapViewOfFile(hMapping_, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||||
if (!data_)
|
if (!data_)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
@ -267,7 +267,7 @@ namespace IACore
|
|||||||
|
|
||||||
#else // LINUX / POSIX
|
#else // LINUX / POSIX
|
||||||
// 1. Open File
|
// 1. Open File
|
||||||
fd_ = ::open(filepath.c_str(), O_RDONLY);
|
fd_ = ::open(filepath.c_str(), O_RDWR);
|
||||||
if (fd_ == -1)
|
if (fd_ == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ namespace IACore
|
|||||||
// 3. mmap
|
// 3. mmap
|
||||||
// PROT_READ: Read only
|
// PROT_READ: Read only
|
||||||
// MAP_PRIVATE: Copy-on-write (safe if you accidentally modify, though we return const)
|
// MAP_PRIVATE: Copy-on-write (safe if you accidentally modify, though we return const)
|
||||||
data_ = ::mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
|
data_ = ::mmap(nullptr, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_, 0);
|
||||||
if (data_ == MAP_FAILED)
|
if (data_ == MAP_FAILED)
|
||||||
{
|
{
|
||||||
data_ = nullptr;
|
data_ = nullptr;
|
||||||
|
|||||||
@ -26,6 +26,8 @@
|
|||||||
# include <bit>
|
# include <bit>
|
||||||
# include <new>
|
# include <new>
|
||||||
# include <span>
|
# include <span>
|
||||||
|
# include <atomic>
|
||||||
|
# include <thread>
|
||||||
# include <limits>
|
# include <limits>
|
||||||
# include <cstring>
|
# include <cstring>
|
||||||
# include <cstddef>
|
# include <cstddef>
|
||||||
@ -534,6 +536,9 @@ using StringStream = std::stringstream;
|
|||||||
using HRClock = std::chrono::high_resolution_clock;
|
using HRClock = std::chrono::high_resolution_clock;
|
||||||
using HRTimePoint = std::chrono::time_point<HRClock>;
|
using HRTimePoint = std::chrono::time_point<HRClock>;
|
||||||
|
|
||||||
|
using Mutex = std::mutex;
|
||||||
|
using LockGuard = std::lock_guard<Mutex>;
|
||||||
|
|
||||||
template<typename... Args> using FormatterString = std::format_string<Args...>;
|
template<typename... Args> using FormatterString = std::format_string<Args...>;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -40,6 +40,35 @@ namespace IACore
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Async Execution
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns a jthread.
|
||||||
|
// - Store it if you want to wait for it later (join).
|
||||||
|
// - If you destroy the returned jthread immediately, it will BLOCK (join) by design.
|
||||||
|
// - If you want "fire and forget", call .detach() on the returned thread.
|
||||||
|
STATIC std::jthread RunAsync(String cmd, String args, Function<VOID(StringView)> onOutputLine,
|
||||||
|
Function<VOID(tl::expected<INT32, String>)> onComplete)
|
||||||
|
{
|
||||||
|
// We capture arguments by VALUE (=) to ensure the thread owns its own copies of the strings.
|
||||||
|
return std::jthread([=, cmd = std::move(cmd), args = std::move(args)]() mutable {
|
||||||
|
tl::expected<INT32, String> result = tl::make_unexpected("Not started");
|
||||||
|
|
||||||
|
#if IA_PLATFORM_WINDOWS
|
||||||
|
result = RunWindows(cmd, args, onOutputLine);
|
||||||
|
#else
|
||||||
|
result = RunPosix(cmd, args, onOutputLine);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Report final result to the callback
|
||||||
|
if (onComplete)
|
||||||
|
{
|
||||||
|
onComplete(std::move(result));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Output Buffering Helper
|
// Output Buffering Helper
|
||||||
|
|||||||
96
Src/IACore/inc/IACore/SocketOps.hpp
Normal file
96
Src/IACore/inc/IACore/SocketOps.hpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||||
|
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <IACore/PCH.hpp>
|
||||||
|
|
||||||
|
#if IA_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
# include <winsock2.h>
|
||||||
|
# pragma comment(lib, "ws2_32.lib")
|
||||||
|
# define CLOSE_SOCKET(s) closesocket(s)
|
||||||
|
# define IS_VALID_SOCKET(s) (s != INVALID_SOCKET)
|
||||||
|
using SocketHandle = SOCKET;
|
||||||
|
|
||||||
|
#elif IA_PLATFORM_UNIX
|
||||||
|
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# define CLOSE_SOCKET(s) close(s)
|
||||||
|
# define IS_VALID_SOCKET(s) (s >= 0)
|
||||||
|
# define INVALID_SOCKET -1
|
||||||
|
using SocketHandle = int;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# warning "IACore SocketOps is not supported on this platform."
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace IACore
|
||||||
|
{
|
||||||
|
class SocketOps
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STATIC VOID Initialize()
|
||||||
|
{
|
||||||
|
#if IA_PLATFORM_WINDOWS
|
||||||
|
WSADATA wsaData;
|
||||||
|
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC VOID Terminate()
|
||||||
|
{
|
||||||
|
#if IA_PLATFORM_WINDOWS
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC BOOL IsPortAvailableTCP(IN UINT16 port)
|
||||||
|
{
|
||||||
|
return IsPortAvailable(port, SOCK_STREAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC BOOL IsPortAvailableUDP(IN UINT16 port)
|
||||||
|
{
|
||||||
|
return IsPortAvailable(port, SOCK_DGRAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
STATIC BOOL IsPortAvailable(IN UINT16 port, IN INT32 type)
|
||||||
|
{
|
||||||
|
SocketHandle sock = socket(AF_INET, type, IPPROTO_UDP);
|
||||||
|
if (!IS_VALID_SOCKET(sock))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sockaddr_in addr{};
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
bool isFree = false;
|
||||||
|
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == 0)
|
||||||
|
isFree = true;
|
||||||
|
|
||||||
|
CLOSE_SOCKET(sock);
|
||||||
|
|
||||||
|
return isFree;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace IACore
|
||||||
Reference in New Issue
Block a user