Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

279 lines
6.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Trace/Config.h"
#if TRACE_PRIVATE_MINIMAL_ENABLED && PLATFORM_APPLE
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <netdb.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
namespace UE {
namespace Trace {
namespace Private {
////////////////////////////////////////////////////////////////////////////////
UPTRINT ThreadCreate(const ANSICHAR* Name, void (*Entry)())
{
void* (*PthreadThunk)(void*) = [] (void* Param) -> void * {
typedef void (*EntryType)(void);
(EntryType(Param))();
return nullptr;
};
pthread_t ThreadHandle;
if (pthread_create(&ThreadHandle, nullptr, PthreadThunk, reinterpret_cast<void *>(Entry)) != 0)
{
return 0;
}
return reinterpret_cast<UPTRINT>(ThreadHandle);
}
////////////////////////////////////////////////////////////////////////////////
void ThreadSleep(uint32 Milliseconds)
{
usleep(Milliseconds * 1000U);
}
////////////////////////////////////////////////////////////////////////////////
void ThreadJoin(UPTRINT Handle)
{
pthread_join(reinterpret_cast<pthread_t>(Handle), nullptr);
}
////////////////////////////////////////////////////////////////////////////////
void ThreadDestroy(UPTRINT Handle)
{
// no-op
}
////////////////////////////////////////////////////////////////////////////////
uint64 TimeGetFrequency()
{
mach_timebase_info_data_t Info;
mach_timebase_info(&Info);
return (uint64(1 * 1000 * 1000 * 1000) * uint64(Info.denom)) / uint64(Info.numer);
}
////////////////////////////////////////////////////////////////////////////////
TRACELOG_API uint64 TimeGetTimestamp()
{
return mach_absolute_time();
}
////////////////////////////////////////////////////////////////////////////////
static bool TcpSocketSetNonBlocking(int Socket, bool bNonBlocking)
{
int Flags = fcntl(Socket, F_GETFL, 0);
if (Flags == -1)
{
return false;
}
Flags = bNonBlocking ? (Flags|O_NONBLOCK) : (Flags & ~O_NONBLOCK);
return fcntl(Socket, F_SETFL, Flags) >= 0;
}
////////////////////////////////////////////////////////////////////////////////
UPTRINT TcpSocketConnect(const ANSICHAR* Host, uint16 Port)
{
#if PLATFORM_MAC // We're only accepting named hosts on desktop platforms
struct FAddrInfoPtr
{
~FAddrInfoPtr() { freeaddrinfo(Value); }
addrinfo* operator -> () { return Value; }
addrinfo** operator & () { return &Value; }
addrinfo* Value;
};
FAddrInfoPtr Info;
addrinfo Hints = {};
Hints.ai_family = AF_INET;
Hints.ai_socktype = SOCK_STREAM;
Hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(Host, nullptr, &Hints, &Info))
{
return 0;
}
if (&Info == nullptr)
{
return 0;
}
auto* SockAddr = (sockaddr_in*)Info->ai_addr;
SockAddr->sin_port = htons(Port);
int SockAddrSize = int(Info->ai_addrlen);
#else
sockaddr_in SockAddrIp;
SockAddrIp.sin_family = AF_INET;
SockAddrIp.sin_addr.s_addr = inet_addr(Host);
SockAddrIp.sin_port = htons(Port);
auto* SockAddr = &SockAddrIp;
int SockAddrSize = sizeof(SockAddrIp);
#endif
int Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Socket < 0)
{
return 0;
}
int Result = connect(Socket, (sockaddr*)SockAddr, SockAddrSize);
if (Result < 0)
{
close(Socket);
return 0;
}
if (!TcpSocketSetNonBlocking(Socket, false))
{
close(Socket);
return 0;
}
return UPTRINT(Socket + 1);
}
////////////////////////////////////////////////////////////////////////////////
UPTRINT TcpSocketListen(uint16 Port)
{
int Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Socket < 0)
{
return 0;
}
sockaddr_in SockAddr;
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = 0;
SockAddr.sin_port = htons(Port);
int Result = bind(Socket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr));
if (Result < 0)
{
close(Socket);
return 0;
}
Result = listen(Socket, 1);
if (Result < 0)
{
close(Socket);
return 0;
}
if (!TcpSocketSetNonBlocking(Socket, true))
{
close(Socket);
return 0;
}
return UPTRINT(Socket + 1);
}
////////////////////////////////////////////////////////////////////////////////
int32 TcpSocketAccept(UPTRINT Socket, UPTRINT& Out)
{
int Inner = int(Socket - 1);
Inner = accept(Inner, nullptr, nullptr);
if (Inner < 0)
{
return (errno == EAGAIN || errno == EWOULDBLOCK) - 1; // 0 if would block else -1
}
if (!TcpSocketSetNonBlocking(Inner, false))
{
close(Inner);
return 0;
}
Out = UPTRINT(Inner + 1);
return 1;
}
////////////////////////////////////////////////////////////////////////////////
bool TcpSocketHasData(UPTRINT Socket)
{
int Inner = int(Socket - 1);
fd_set FdSet;
FD_ZERO(&FdSet);
FD_SET(Inner, &FdSet);
timeval TimeVal = {};
int result = select(Inner + 1, &FdSet, nullptr, nullptr, &TimeVal);
return ((result != 0) || ((result == -1) && (errno == ETIMEDOUT)));
}
////////////////////////////////////////////////////////////////////////////////
bool IoWrite(UPTRINT Handle, const void* Data, uint32 Size)
{
int Inner = int(Handle - 1);
return (write(Inner, Data, Size) == Size);
}
////////////////////////////////////////////////////////////////////////////////
int32 IoRead(UPTRINT Handle, void* Data, uint32 Size)
{
int Inner = int(Handle - 1);
return read(Inner, Data, Size);
}
////////////////////////////////////////////////////////////////////////////////
void IoClose(UPTRINT Handle)
{
int Inner = int(Handle - 1);
close(Inner);
}
////////////////////////////////////////////////////////////////////////////////
UPTRINT FileOpen(const ANSICHAR* Path)
{
int Flags = O_CREAT|O_WRONLY|O_TRUNC|O_SHLOCK;
int Mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
int Out = open(Path, Flags, Mode);
if (Out < 0)
{
return 0;
}
return UPTRINT(Out + 1);
}
////////////////////////////////////////////////////////////////////////////////
int32 GetLastErrorCode()
{
return errno;
}
////////////////////////////////////////////////////////////////////////////////
bool GetErrorMessage(char* OutBuffer, uint32 BufferSize, int32 ErrorCode)
{
const char* ErrorMessage = strerror(ErrorCode);
const bool bResult = strncpy(OutBuffer, ErrorMessage, BufferSize) != 0;
OutBuffer[BufferSize-1] = 0;
return bResult;
}
} // namespace Private
} // namespace Trace
} // namespace UE
#endif // TRACE_PRIVATE_MINIMAL_ENABLED