uint32 FTcpMessageTransportConnection::Run() { while (bRun) { // Try sending and receiving messages and detect if they fail or if another connection error is reported. if ((!ReceiveMessages() || !SendMessages() || Socket->GetConnectionState() == SCS_ConnectionError) && bRun) { // Disconnected. Reconnect if requested. if (ConnectionRetryDelay > 0) { UE_LOG(LogTcpMessaging, Verbose, TEXT("Connection to '%s' failed, retrying..."), *RemoteEndpoint.ToString()); FPlatformProcess::Sleep(ConnectionRetryDelay); ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(Socket); Socket = FTcpSocketBuilder(TEXT("FTcpMessageTransport.RemoteConnection")); if (Socket && Socket->Connect(RemoteEndpoint.ToInternetAddr().Get())) { bSentHeader = false; bReceivedHeader = false; UpdateConnectionState(STATE_DisconnectReconnectPending); RemoteNodeId.Invalidate(); } else { if (Socket) { ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(Socket); Socket = nullptr; } bRun = false; } } else { bRun = false; } } FPlatformProcess::Sleep(0.0f); } UpdateConnectionState(STATE_Disconnected); RemoteNodeId.Invalidate(); ClosedTime = FDateTime::UtcNow(); // Clear the delegate to remove a reference to this connection ConnectionStateChangedDelegate.Unbind(); return 0; }
ECommandResult::Type FSubversionSourceControlProvider::IssueCommand(FSubversionSourceControlCommand& InCommand, const bool bSynchronous) { if ( !bSynchronous && GThreadPool != NULL ) { // Queue this to our worker thread(s) for resolving GThreadPool->AddQueuedWork(&InCommand); CommandQueue.Add(&InCommand); return ECommandResult::Succeeded; } else { InCommand.bCommandSuccessful = InCommand.DoWork(); UpdateConnectionState(InCommand); InCommand.Worker->UpdateStates(); OutputCommandMessages(InCommand); // Callback now if present. When asynchronous, this callback gets called from Tick(). ECommandResult::Type Result = InCommand.bCommandSuccessful ? ECommandResult::Succeeded : ECommandResult::Failed; InCommand.OperationCompleteDelegate.ExecuteIfBound(InCommand.Operation, Result); return Result; } }
void FSubversionSourceControlProvider::Tick() { bool bStatesUpdated = false; for (int32 CommandIndex = 0; CommandIndex < CommandQueue.Num(); ++CommandIndex) { FSubversionSourceControlCommand& Command = *CommandQueue[CommandIndex]; if (Command.bExecuteProcessed) { // Remove command from the queue CommandQueue.RemoveAt(CommandIndex); // let command update the states of any files bStatesUpdated |= Command.Worker->UpdateStates(); // update connection state UpdateConnectionState(Command); // dump any messages to output log OutputCommandMessages(Command); // run the completion delegate if we have one bound Command.OperationCompleteDelegate.ExecuteIfBound(Command.Operation, Command.bCommandSuccessful ? ECommandResult::Succeeded : ECommandResult::Failed); //commands that are left in the array during a tick need to be deleted if(Command.bAutoDelete) { // Only delete commands that are not running 'synchronously' delete &Command; } // only do one command per tick loop, as we dont want concurrent modification // of the command queue (which can happen in the completion delegate) break; } } if(bStatesUpdated) { OnSourceControlStateChanged.Broadcast(); } }
bool FTcpMessageTransportConnection::ReceiveMessages() { uint32 PendingDataSize = 0; // check if the socket has closed { int32 BytesRead; uint8 Dummy; if (!Socket->Recv(&Dummy, 1, BytesRead, ESocketReceiveFlags::Peek)) { return false; } } if (!bReceivedHeader) { if (Socket->HasPendingData(PendingDataSize) && PendingDataSize >= sizeof(FTcpMessageHeader)) { FArrayReader HeaderData = FArrayReader(true); HeaderData.SetNumUninitialized(sizeof(FTcpMessageHeader)); int32 BytesRead = 0; if (!Socket->Recv(HeaderData.GetData(), sizeof(FTcpMessageHeader), BytesRead)) { return false; } check(BytesRead == sizeof(FTcpMessageHeader)); TotalBytesReceived += BytesRead; FTcpMessageHeader MessageHeader; HeaderData << MessageHeader; if (!MessageHeader.IsValid()) { return false; } else { RemoteNodeId = MessageHeader.GetNodeId(); RemoteProtocolVersion = MessageHeader.GetVersion(); bReceivedHeader = true; OpenedTime = FDateTime::UtcNow(); UpdateConnectionState(STATE_Connected); } } else { // no header yet return true; } } // keep going until we have no data. for(;;) { int32 BytesRead = 0; // See if we're in the process of receiving a (large) message if (RecvMessageDataRemaining == 0) { // no partial message. Try to receive the size of a message if (!Socket->HasPendingData(PendingDataSize) || (PendingDataSize < sizeof(uint32))) { // no messages return true; } FArrayReader MessagesizeData = FArrayReader(true); MessagesizeData.SetNumUninitialized(sizeof(uint32)); // read message size from the stream BytesRead = 0; if (!Socket->Recv(MessagesizeData.GetData(), sizeof(uint32), BytesRead)) { return false; } check(BytesRead == sizeof(uint32)); TotalBytesReceived += BytesRead; // Setup variables to receive the message MessagesizeData << RecvMessageDataRemaining; RecvMessageData = MakeShareable(new FArrayReader(true)); RecvMessageData->SetNumUninitialized(RecvMessageDataRemaining); check(RecvMessageDataRemaining > 0); } BytesRead = 0; if (!Socket->Recv(RecvMessageData->GetData() + RecvMessageData->Num() - RecvMessageDataRemaining, RecvMessageDataRemaining, BytesRead)) { return false; } if (BytesRead > 0) { check(BytesRead <= RecvMessageDataRemaining); TotalBytesReceived += BytesRead; RecvMessageDataRemaining -= BytesRead; if (RecvMessageDataRemaining == 0) { // @todo gmp: move message deserialization into an async task FTcpDeserializedMessage* DeserializedMessage = new FTcpDeserializedMessage(nullptr); if (DeserializedMessage->Deserialize(RecvMessageData)) { Inbox.Enqueue(MakeShareable(DeserializedMessage)); } RecvMessageData.Reset(); } } else { // no data return true; } } }