// Copyright 2022 David Romanski (Socke). All Rights Reserved. #include "SocketClientTCPSendDataThead.h" FSocketClientTCPSendDataThead::FSocketClientTCPSendDataThead(USocketClientBPLibrary* socketClientLibP, USocketClientTCPClient* tcpClientP, FString clientConnectionIDP) : socketClientLib(socketClientLibP), tcpClient(tcpClientP), clientConnectionID(clientConnectionIDP) { FString threadName = "FSendDataToServerThread" + FGuid::NewGuid().ToString(); thread = FRunnableThread::Create(this, *threadName, 0, EThreadPriority::TPri_Normal); } FSocketClientTCPSendDataThead::~FSocketClientTCPSendDataThead() { delete thread; } uint32 FSocketClientTCPSendDataThead::Run(){ if (tcpClient == nullptr) { UE_LOG(LogTemp, Error, TEXT("Class is not initialized.")); return 0; } /*if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 20.0f, FColor::Green, TEXT("tcp socket 1"));*/ FString clientConnectionIDGlobal = clientConnectionID; USocketClientBPLibrary* socketClientLibGlobal = socketClientLib; //message wrapping FString stringSeparator = FString(); uint8 byteSeparator = 0x00; ESocketClientTCPSeparator messageWrapping = ESocketClientTCPSeparator::E_None; tcpClient->getTcpSeparator(stringSeparator, byteSeparator, messageWrapping); TArray stringSeparatorArray = stringSeparator.GetCharArray(); if (stringSeparatorArray.Num() > 0 && stringSeparatorArray.Last() == 0x00) { stringSeparatorArray.RemoveAt(stringSeparatorArray.Num() - 1, 1, true); } if (messageWrapping == ESocketClientTCPSeparator::E_LengthSeparator && stringSeparatorArray.Num() == 0) { messageWrapping = ESocketClientTCPSeparator::E_None; UE_LOG(LogTemp, Warning, TEXT("Socket Client Plugin: Separator mode is set to String but there is no String Separator. Mode changed to none.")); } // get the socket FSocket* socket = tcpClient->getSocket(); int32 sent = 0; while (tcpClient->isRun()) { // try to connect to the server if (socket == NULL || socket == nullptr) { UE_LOG(LogTemp, Error, TEXT("Connection not exist.")); //AsyncTask(ENamedThreads::GameThread, [clientConnectionIDGlobal, socketClientLibGlobal]() { // if (socketClientLibGlobal != nullptr) { // socketClientLibGlobal->onsocketClientTCPConnectionEventDelegate.Broadcast(false, "Connection not exist:" + clientConnectionIDGlobal, clientConnectionIDGlobal); // socketClientLibGlobal->closeSocketClientConnection(); // } //}); break; } if (socket != nullptr && tcpClient->isRun()) { while (messageQueue.IsEmpty() == false) { FString m; messageQueue.Dequeue(m); FTCHARToUTF8 Convert(*m); sent = 0; TArray byteCache; switch (messageWrapping) { case ESocketClientTCPSeparator::E_None: byteCache.Append((uint8*)Convert.Get(), Convert.Length()); break; case ESocketClientTCPSeparator::E_ByteSeparator: byteCache.Append((uint8*)Convert.Get(), Convert.Length()); byteCache.Add(byteSeparator); break; case ESocketClientTCPSeparator::E_StringSeparator: { m += stringSeparator; FTCHARToUTF8 ConvertWithSeparator(*m); byteCache.Append((uint8*)ConvertWithSeparator.Get(), ConvertWithSeparator.Length()); } break; case ESocketClientTCPSeparator::E_LengthSeparator: if (FGenericPlatformProperties::IsLittleEndian()) { byteCache.Add(0x00); } else { byteCache.Add(0x01); } byteCache.SetNum(5); int32 dataLength = Convert.Length(); FMemory::Memcpy(byteCache.GetData() + 1, &dataLength, 4); byteCache.Append((uint8*)Convert.Get(), Convert.Length()); break; } socket->Send(byteCache.GetData(), byteCache.Num(), sent); } while (byteArrayQueue.IsEmpty() == false) { TArray byteCache; byteArrayQueue.Dequeue(byteCache); sent = 0; switch (messageWrapping) { case ESocketClientTCPSeparator::E_ByteSeparator: byteCache.Add(byteSeparator); break; case ESocketClientTCPSeparator::E_StringSeparator: { FTCHARToUTF8 ConvertWithSeparator(*stringSeparator); byteCache.Append((uint8*)ConvertWithSeparator.Get(), ConvertWithSeparator.Length()); } break; case ESocketClientTCPSeparator::E_LengthSeparator: byteCache.InsertZeroed(0, 5); if (FGenericPlatformProperties::IsLittleEndian() == false) { uint8 a = 0x01; FMemory::Memcpy(byteCache.GetData(), &a, 1); } int32 dataLength = byteCache.Num() - 5; FMemory::Memcpy(byteCache.GetData() + 1, &dataLength, 4); break; } socket->Send(byteCache.GetData(), byteCache.Num(), sent); } } if (tcpClient->isRun()) { pauseThread(true); //workaround. suspend do not work on all platforms. lets sleep while (paused && tcpClient->isRun()) { FPlatformProcess::Sleep(0.01); } } } return 0; } void FSocketClientTCPSendDataThead::sendMessage(FString messageP, TArray byteArrayP) { if (messageP.Len() > 0) messageQueue.Enqueue(messageP); if (byteArrayP.Num() > 0) byteArrayQueue.Enqueue(byteArrayP); pauseThread(false); } void FSocketClientTCPSendDataThead::pauseThread(bool pause) { paused = pause; if (thread != nullptr) thread->Suspend(pause); }