Esempio n. 1
0
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);
			}
		}
	}
}
Esempio n. 2
0
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."));
			}
		}
	}
}