void PacketReceiverTCP::process() { FSocket *socket = pNetworkInterface_->socket(); uint32 DataSize = 0; while (socket->HasPendingData(DataSize)) { pBuffer_->resize(FMath::Min(DataSize, 65507u)); int32 BytesRead = 0; if (socket->Recv(pBuffer_->data(), pBuffer_->size(), BytesRead)) { pBuffer_->wpos(BytesRead); if (pNetworkInterface_->filter()) { pNetworkInterface_->filter()->recv(pMessageReader_, pBuffer_); } else { pMessageReader_->process(pBuffer_->data(), 0, BytesRead); } } } }
bool FPerfCounters::Tick(float DeltaTime) { // if we didn't get a socket, don't tick if (Socket == nullptr) { return false; } // accept any connections static const FString PerfCounterRequest = TEXT("FPerfCounters Request"); FSocket* IncomingConnection = Socket->Accept(PerfCounterRequest); if (IncomingConnection) { // make sure this is non-blocking bool bSuccess = false; IncomingConnection->SetNonBlocking(true); // read any data that's ready // NOTE: this is not a full HTTP implementation, just enough to be usable by curl uint8 Buffer[2*1024] = { 0 }; int32 DataLen = 0; if (IncomingConnection->Recv(Buffer, sizeof(Buffer)-1, DataLen, ESocketReceiveFlags::None)) { // scan the buffer for a line FUTF8ToTCHAR WideBuffer(reinterpret_cast<const ANSICHAR*>(Buffer)); const TCHAR* BufferEnd = FCString::Strstr(WideBuffer.Get(), TEXT("\r\n")); if (BufferEnd != nullptr) { // crack into pieces FString MainLine(BufferEnd - WideBuffer.Get(), WideBuffer.Get()); TArray<FString> Tokens; MainLine.ParseIntoArrayWS(Tokens); if (Tokens.Num() >= 2) { FString Body; int ResponseCode = 200; // handle the request if (Tokens[0] != TEXT("GET")) { Body = FString::Printf(TEXT("{ \"error\": \"Method %s not allowed\" }"), *Tokens[0]); ResponseCode = 405; } else if (Tokens[1] == TEXT("/stats")) { Body = ToJson(); } else { Body = FString::Printf(TEXT("{ \"error\": \"%s not found\" }"), *Tokens[1]); ResponseCode = 404; } // send the response headers FString Header = FString::Printf(TEXT("HTTP/1.0 %d\r\nContent-Length: %d\r\nContent-Type: application/json\r\n\r\n"), ResponseCode, Body.Len()); if (SendAsUtf8(IncomingConnection, Header) && SendAsUtf8(IncomingConnection, Body)) { bSuccess = true; } } } } // log if we didn't succeed if (!bSuccess) { UE_LOG(LogPerfCounters, Warning, TEXT("FPerfCounters was unable to send a JSON response (or sent partial response)")); } // close the socket (whether we processed or not IncomingConnection->Close(); ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(IncomingConnection); } // keep ticking return true; }
void FLiveEditorListenServer::Tick( float DeltaTime ) { #if !UE_BUILD_SHIPPING if ( !PendingClients.IsEmpty() ) { FSocket *Client = NULL; while( PendingClients.Dequeue(Client) ) { Clients.Add(Client); } } // remove closed connections for (int32 ClientIndex = Clients.Num() - 1; ClientIndex >= 0; --ClientIndex) { if ( Clients[ClientIndex]->GetConnectionState() != SCS_Connected ) { Clients.RemoveAtSwap(ClientIndex); } } //poll for data for ( TArray<class FSocket*>::TIterator ClientIt(Clients); ClientIt; ++ClientIt ) { FSocket *Client = *ClientIt; uint32 DataSize = 0; while ( Client->HasPendingData(DataSize) ) { FArrayReaderPtr Datagram = MakeShareable(new FArrayReader(true)); Datagram->Init(FMath::Min(DataSize, 65507u)); int32 BytesRead = 0; if ( Client->Recv(Datagram->GetData(), Datagram->Num(), BytesRead) ) { nLiveEditorListenServer::FNetworkMessage Message; *Datagram << Message; ReplicateChanges( Message ); TransactionHistory->AppendTransaction( Message.Payload.ClassName, Message.Payload.PropertyName, Message.Payload.PropertyValue ); } } } //Check for any newly Tracked objects TArray<UObject*> NewTrackedObjects; ObjectCache.EvaluatePendingCreations( NewTrackedObjects ); //If there are any newly tracked objects, stuff them with the list of latest changes we've accumulated so far for ( TArray<UObject*>::TIterator NewObjectIt(NewTrackedObjects); NewObjectIt; ++NewObjectIt ) { UObject *NewObject = *NewObjectIt; TMap<FString,FString> Transactions; TransactionHistory->FindTransactionsForObject( NewObject, Transactions ); for ( TMap<FString,FString>::TConstIterator TransactionIt(Transactions); TransactionIt; ++TransactionIt ) { const FString &PropertyName = (*TransactionIt).Key; const FString &PropertyValue = (*TransactionIt).Value; nLiveEditorListenServer::SetPropertyValue( NewObject, PropertyName, PropertyValue ); } } #endif }
void FPerfCounters::TickSocket(float DeltaTime) { checkf(Socket != nullptr, TEXT("FPerfCounters::TickSocket() called without a valid socket!")); // accept any connections static const FString PerfCounterRequest = TEXT("FPerfCounters Request"); FSocket* IncomingConnection = Socket->Accept(PerfCounterRequest); if (IncomingConnection) { if (0) { TSharedRef<FInternetAddr> FromAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); IncomingConnection->GetPeerAddress(*FromAddr); UE_LOG(LogPerfCounters, Log, TEXT("New connection from %s"), *FromAddr->ToString(true)); } // make sure this is non-blocking IncomingConnection->SetNonBlocking(true); new (Connections) FPerfConnection(IncomingConnection); } TArray<FPerfConnection> ConnectionsToClose; for (FPerfConnection& Connection : Connections) { FSocket* ExistingSocket = Connection.Connection; if (ExistingSocket && ExistingSocket->Wait(ESocketWaitConditions::WaitForRead, FTimespan::Zero())) { // read any data that's ready // NOTE: this is not a full HTTP implementation, just enough to be usable by curl uint8 Buffer[2 * 1024] = { 0 }; int32 DataLen = 0; if (ExistingSocket->Recv(Buffer, sizeof(Buffer) - 1, DataLen, ESocketReceiveFlags::None)) { FResponse Response; if (ProcessRequest(Buffer, DataLen, Response)) { if (SendAsUtf8(ExistingSocket, Response.Header)) { if (!SendAsUtf8(ExistingSocket, Response.Body)) { UE_LOG(LogPerfCounters, Warning, TEXT("Unable to send full HTTP response body")); } } else { UE_LOG(LogPerfCounters, Warning, TEXT("Unable to send HTTP response header: %s"), *Response.Header); } } } else { UE_LOG(LogPerfCounters, Warning, TEXT("Unable to immediately receive request header")); } ConnectionsToClose.Add(Connection); } else if (Connection.ElapsedTime > 5.0f) { ConnectionsToClose.Add(Connection); } Connection.ElapsedTime += DeltaTime; } for (FPerfConnection& Connection : ConnectionsToClose) { Connections.RemoveSingleSwap(Connection); FSocket* ClosingSocket = Connection.Connection; if (ClosingSocket) { // close the socket (whether we processed or not) ClosingSocket->Close(); ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ClosingSocket); if (0) { UE_LOG(LogPerfCounters, Log, TEXT("Closed connection.")); } } } }