Files
UnrealEngine/Engine/Source/Programs/Unsync/Private/UnsyncSocket.h
2025-05-18 13:04:45 +08:00

204 lines
4.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include <stdint.h>
#include "UnsyncCommon.h"
#include "UnsyncBuffer.h"
struct tls;
namespace unsync {
class FBuffer;
struct FBufferView;
using FSocketHandle = uintptr_t;
extern const FSocketHandle InvalidSocketHandle;
struct FSocketAddress // opaque buffer that holds socket address
{
FSocketAddress()
{
for (uint64& X : Data64)
X = 0;
}
union
{
char Data[16];
uint64 Data64[2];
};
bool operator==(const FSocketAddress& Other) const { return Data64[0] == Other.Data64[0] && Data64[1] == Other.Data64[1]; }
};
// Returns current host name or empty string if it could not be determined.
std::string GetCurrentHostName();
FSocketHandle SocketListenTcp(const char* Address, uint16 Port);
FSocketHandle SocketAccept(FSocketHandle ListenSocket);
FSocketHandle SocketConnectTcp(const char* DestAddress, uint16 Port);
void SocketClose(FSocketHandle Socket);
int SocketSend(FSocketHandle Socket, const void* Data, size_t DataSize);
int SocketRecvAll(FSocketHandle Socket, void* Data, size_t DataSize);
int SocketRecvAny(FSocketHandle Socket, void* Data, size_t DataSize);
FSocketAddress SocketMakeAddress(const char* Address, uint16 Port);
bool SocketSetRecvTimeout(FSocketHandle Socket, uint32 Seconds);
bool SocketValid(FSocketHandle Socket);
template<typename T>
bool
SocketSendT(FSocketHandle Socket, const T& Data)
{
int SentBytes = SocketSend(Socket, &Data, sizeof(Data));
return SentBytes == sizeof(Data);
}
template<typename T>
bool
SocketRecvT(FSocketHandle Socket, T& Data)
{
return SocketRecvAll(Socket, &Data, sizeof(Data)) == sizeof(Data);
}
enum class ESocketSecurity
{
None,
TLSv1_2,
TLSv1_3,
Unknown
};
const char* ToString(ESocketSecurity Security);
struct FSocketBase
{
UNSYNC_DISALLOW_COPY_ASSIGN(FSocketBase)
explicit FSocketBase(FSocketHandle InHandle) : Handle(InHandle) {}
virtual ~FSocketBase();
virtual int Send(const void* Data, size_t DataSize) = 0;
virtual int RecvAll(void* Data, size_t DataSize) = 0;
virtual int RecvAny(void* Data, size_t DataSize) = 0;
virtual bool IsEncrypted() const = 0;
FSocketHandle Handle = {};
ESocketSecurity Security = ESocketSecurity::None;
};
struct FSocketRaw : FSocketBase
{
explicit FSocketRaw(FSocketHandle InHandle) : FSocketBase(InHandle) {}
virtual int Send(const void* Data, size_t DataSize) override;
virtual int RecvAll(void* Data, size_t DataSize) override;
virtual int RecvAny(void* Data, size_t DataSize) override;
virtual bool IsEncrypted() const override { return false; }
};
enum class ETlsRequirement : uint8 {
None, // Use defaults for the underlying protocol
Preferred, // Try TLS connection, but allow falling back to plaintext if server supports it
Required, // Only allow connections with TLS
};
struct FTlsClientSettings
{
std::string_view Subject = {};
FBufferView CACert = {};
bool bVerifyCertificate = true;
bool bVerifySubject = true;
};
struct FSocketTls : FSocketBase
{
FSocketTls(FSocketHandle InHandle, FTlsClientSettings ClientSettings);
~FSocketTls();
bool IsTlsValid() const { return TlsCtx != nullptr; }
virtual int Send(const void* Data, size_t DataSize) override;
virtual int RecvAll(void* Data, size_t DataSize) override;
virtual int RecvAny(void* Data, size_t DataSize) override;
virtual bool IsEncrypted() const override { return IsTlsValid(); }
tls* TlsCtx = {};
};
template<typename T>
bool
SocketSendT(FSocketBase& Socket, const T& Data)
{
int SentBytes = Socket.Send(&Data, sizeof(Data));
return SentBytes == sizeof(Data);
}
template<typename T>
bool
SocketRecvT(FSocketBase& Socket, T& Data)
{
return Socket.RecvAll(&Data, sizeof(Data)) == sizeof(Data);
}
inline int
SocketSend(FSocketBase& Socket, const void* Data, size_t DataSize)
{
return Socket.Send(Data, DataSize);
}
inline int
SocketRecvAll(FSocketBase& Socket, void* Data, size_t DataSize)
{
return Socket.RecvAll(Data, DataSize);
}
inline int
SocketRecvAny(FSocketBase& Socket, void* Data, size_t DataSize)
{
return Socket.RecvAny(Data, DataSize);
}
inline bool
SocketValid(FSocketBase& Socket)
{
return SocketValid(Socket.Handle);
}
template<typename T>
bool
SendStruct(FSocketBase& Socket, const T& Data)
{
int32 Size = int32(sizeof(Data));
bool bOk = true;
bOk &= SocketSendT(Socket, Size);
bOk &= SocketSendT(Socket, Data);
return bOk;
}
bool SendBuffer(FSocketBase& Socket, const FBufferView& Data);
bool SendBuffer(FSocketBase& Socket, const FBuffer& Data);
template<typename T>
bool
RecvStruct(FSocketBase& Socket, const T& Data)
{
int32 Size = int32(sizeof(Data));
bool bOk = true;
bOk &= SocketRecvT(Socket, Size);
bOk &= SocketRecvT(Socket, Data);
return bOk;
}
} // namespace unsync