Files
UnrealEngine/Engine/Source/Runtime/CookOnTheFly/Private/TCPTransport.cpp
2025-05-18 13:04:45 +08:00

116 lines
2.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "TCPTransport.h"
#include "NetworkMessage.h"
#include "SocketSubsystem.h"
#include "IPAddress.h"
#include "Sockets.h"
#include "MultichannelTcpSocket.h"
#include "Interfaces/IPv4/IPv4Endpoint.h"
#include "CookOnTheFly.h"
FTCPTransport::FTCPTransport()
:FileSocket(NULL)
,MCSocket(NULL)
{
}
bool FTCPTransport::Initialize(const TCHAR* InHostIp)
{
ISocketSubsystem* SSS = ISocketSubsystem::Get();
FString HostIp = InHostIp;
// the protocol isn't required for tcp it's assumed by default
HostIp.RemoveFromStart(TEXT("tcp://"));
// convert the string to a ip addr structure
// DEFAULT_TCP_FILE_SERVING_PORT is overridden
TSharedRef<FInternetAddr> Addr = SSS->CreateInternetAddr();
bool bIsValid;
FIPv4Endpoint FileServerEndpoint;
if (FIPv4Endpoint::Parse(InHostIp, FileServerEndpoint) || FIPv4Endpoint::FromHostAndPort(InHostIp, FileServerEndpoint))
{
Addr->SetIp(FileServerEndpoint.Address.Value);
Addr->SetPort(FileServerEndpoint.Port == 0 ? DEFAULT_TCP_FILE_SERVING_PORT : FileServerEndpoint.Port);
bIsValid = true;
}
else
{
Addr->SetIp(*HostIp, bIsValid);
Addr->SetPort(DEFAULT_TCP_FILE_SERVING_PORT);
}
if (bIsValid)
{
// create the socket
FileSocket = SSS->CreateSocket(NAME_Stream, TEXT("COTF tcp"), Addr->GetProtocolType());
// try to connect to the server
if (FileSocket == nullptr || FileSocket->Connect(*Addr) == false)
{
// on failure, shut it all down
SSS->DestroySocket(FileSocket);
FileSocket = NULL;
UE_LOG(LogCookOnTheFly, Error, TEXT("Failed to connect to COTF server at %s."), *Addr->ToString(true));
}
HostName = Addr->ToString(false);
}
#if USE_MCSOCKET_FOR_NFS
MCSocket = new FMultichannelTcpSocket(FileSocket, 64 * 1024 * 1024);
#endif
return ( FileSocket || MCSocket );
}
bool FTCPTransport::SendPayload(const TArray<uint8>& Payload)
{
#if USE_MCSOCKET_FOR_NFS
return FNFSMessageHeader::WrapAndSendPayload(Payload, FSimpleAbstractSocket_FMultichannelTCPSocket(MCSocket, NFS_Channels::Main));
#else
return FNFSMessageHeader::WrapAndSendPayload(Payload, FSimpleAbstractSocket_FSocket(FileSocket));
#endif
}
bool FTCPTransport::ReceivePayload(FArrayReader& Payload)
{
#if USE_MCSOCKET_FOR_NFS
return FNFSMessageHeader::ReceivePayload(Payload, FSimpleAbstractSocket_FMultichannelTCPSocket(MCSocket, NFS_Channels::Main));
#else
return FNFSMessageHeader::ReceivePayload(Payload, FSimpleAbstractSocket_FSocket(FileSocket));
#endif
}
bool FTCPTransport::HasPendingPayload()
{
#if USE_MCSOCKET_FOR_NFS
return MCSocket->DataAvailable(NFS_Channels::Main) > 0;
#else
uint32 PendingDataSize;
return FileSocket->HasPendingData(PendingDataSize);
#endif
}
void FTCPTransport::Disconnect()
{
#if USE_MCSOCKET_FOR_NFS
checkNoEntry();
#else
FileSocket->Close();
#endif
}
FTCPTransport::~FTCPTransport()
{
// on failure, shut it all down
delete MCSocket;
MCSocket = NULL;
ISocketSubsystem::Get()->DestroySocket(FileSocket);
FileSocket = NULL;
}