Esempio n. 1
0
bool FLiveEditorManager::ConnectToRemoteHost( FString IPAddress )
{
	IPAddress.Replace( TEXT(" "), TEXT("") );

	TArray<FString> Parts;
	IPAddress.ParseIntoArray( Parts, TEXT("."), true );
	if ( Parts.Num() != 4 )
		return false;

	uint8 NumericParts[4];
	for ( int32 i = 0; i < 4; ++i )
	{
		NumericParts[i] = FCString::Atoi( *Parts[i] );
	}

	FSocket* Socket = FTcpSocketBuilder(TEXT("FLiveEditorManager.RemoteConnection"));
	FIPv4Endpoint Endpoint(FIPv4Address(NumericParts[0], NumericParts[1], NumericParts[2], NumericParts[3]), LIVEEDITORLISTENSERVER_DEFAULT_PORT);
	if ( Socket->Connect(*Endpoint.ToInternetAddr()) )
	{
		RemoteConnections.Add(IPAddress, Socket);
		return true;
	}
	else
	{
		return false;
	}
}
Esempio n. 2
0
void FLiveEditorManager::BroadcastValueUpdate( const FString &ClassName, const FString &PropertyName, const FString &PropertyValue )
{
	// remove closed connections
	for ( TMap<FString, class FSocket *>::TIterator ConnectionIt(RemoteConnections); ConnectionIt; ++ConnectionIt )
	{
		FSocket *Connection = (*ConnectionIt).Value;
		if ( Connection->GetConnectionState() != SCS_Connected )
		{
			RemoteConnections.Remove( (*ConnectionIt).Key );
		}
	}

	//no one to talk to, exit
	if ( RemoteConnections.Num() == 0 )
	{
		return;
	}

	nLiveEditorListenServer::FNetworkMessage Message;
	Message.Type = nLiveEditorListenServer::CLASSDEFAULT_OBJECT_PROPERTY;
	Message.Payload.ClassName = ClassName;
	Message.Payload.PropertyName = PropertyName;
	Message.Payload.PropertyValue = PropertyValue;

	TSharedPtr<FArrayWriter> Datagram = MakeShareable(new FArrayWriter(true));
	*Datagram << Message;

	for ( TMap<FString, class FSocket *>::TIterator ConnectionIt(RemoteConnections); ConnectionIt; ++ConnectionIt )
	{
		FSocket *Connection = (*ConnectionIt).Value;
		int32 BytesSent = 0;
		Connection->Send( Datagram->GetData(), Datagram->Num(), BytesSent );
	}
}
Esempio n. 3
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);
			}
		}
	}
}
uint32 FNetworkFileServer::Run( )
{
	Running.Set(true); 
	// go until requested to be done
	while (!StopRequested.GetValue())
	{
		bool bReadReady = false;

		// clean up closed connections
		for (int32 ConnectionIndex = 0; ConnectionIndex < Connections.Num(); ++ConnectionIndex)
		{
			FNetworkFileServerClientConnectionThreaded* Connection = Connections[ConnectionIndex];

			if (!Connection->IsRunning())
			{
				UE_LOG(LogFileServer, Display, TEXT( "Client %s disconnected." ), *Connection->GetDescription() );
				Connections.RemoveAtSwap(ConnectionIndex);
				delete Connection;
			}
		}

		// check for incoming connections
		if (Socket->HasPendingConnection(bReadReady) && bReadReady)
		{
			FSocket* ClientSocket = Socket->Accept(TEXT("Remote Console Connection"));

			if (ClientSocket != NULL)
			{
				TSharedPtr<FInternetAddr> Addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
				ClientSocket->GetAddress(*Addr);
				TSharedPtr<FInternetAddr> PeerAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
				ClientSocket->GetPeerAddress(*PeerAddr);

				for ( auto PreviousConnection : Connections )
				{
					TSharedPtr<FInternetAddr> PreviousAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();;
					PreviousConnection->GetAddress( *PreviousAddr );
					TSharedPtr<FInternetAddr> PreviousPeerAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();;
					PreviousConnection->GetPeerAddress( *PreviousPeerAddr );
					if ( ( *Addr == *PreviousAddr ) &&
						(*PeerAddr == *PreviousPeerAddr ) )
					{
						// kill hte connection 
						PreviousConnection->Stop();
						UE_LOG(LogFileServer, Warning, TEXT( "Killing client connection %s because new client connected from same address." ), *PreviousConnection->GetDescription() );
					}
				}

				FNetworkFileServerClientConnectionThreaded* Connection = new FNetworkFileServerClientConnectionThreaded(ClientSocket, FileRequestDelegate, RecompileShadersDelegate, ActiveTargetPlatforms);
				Connections.Add(Connection);
				UE_LOG(LogFileServer, Display, TEXT( "Client %s connected." ), *Connection->GetDescription() );
			}
		}

		FPlatformProcess::Sleep(0.25f);
	}

	return 0;
}
Esempio n. 5
0
FSocket* FSocket::NewLC(const StringBuffer& peer, int32_t port)
{
    FSocket* self = new ( ELeave ) FSocket();
    CleanupStack::PushL( self );
    self->ConstructL(peer, port);

    return self;
}
Esempio n. 6
0
bool UNetworkManager::Start(int32 InPortNum) // Restart the server if configuration changed
{
	if (InPortNum == this->PortNum && this->bIsListening) return true; // Already started

	if (ConnectionSocket) // Release previous connection
	{
		ConnectionSocket->Close();
		ConnectionSocket = NULL;
	}

	if (TcpListener) // Delete previous configuration first
	{
		UE_LOG(LogUnrealCV, Warning, TEXT("Stop previous server"));
		TcpListener->Stop(); // TODO: test the robustness, will this operation successful?
		delete TcpListener;
	}

	this->PortNum = InPortNum; // Start a new TCPListener
	FIPv4Address IPAddress = FIPv4Address(0, 0, 0, 0);
	// int32 PortNum = this->PortNum; // Make this configuable
	FIPv4Endpoint Endpoint(IPAddress, PortNum);

	FSocket* ServerSocket = FTcpSocketBuilder(TEXT("FTcpListener server")) // TODO: Need to realease this socket
		// .AsReusable()
		.BoundToEndpoint(Endpoint)
		.Listening(8);

	if (ServerSocket)
	{
		int32 NewSize = 0;
		ServerSocket->SetReceiveBufferSize(2 * 1024 * 1024, NewSize);
	}
	else
	{
		this->bIsListening = false;
		UE_LOG(LogUnrealCV, Warning, TEXT("Cannot start listening on port %d, Port might be in use"), PortNum);
		return false;
	}

	TcpListener = new FTcpListener(*ServerSocket);
	// TcpListener = new FTcpListener(Endpoint); // This will be released after start
	// In FSocket, when a FSocket is set as reusable, it means SO_REUSEADDR, not SO_REUSEPORT.  see SocketsBSD.cpp
	TcpListener->OnConnectionAccepted().BindUObject(this, &UNetworkManager::Connected);
	if (TcpListener->Init())
	{
		this->bIsListening = true;
		UE_LOG(LogUnrealCV, Warning, TEXT("Start listening on %d"), PortNum);
		return true;
	}
	else
	{
		this->bIsListening = false;
		UE_LOG(LogUnrealCV, Error, TEXT("Can not start listening on port %d"), PortNum);
		return false;
	}
}
Esempio n. 7
0
FSocket* FSocket::NewL(const StringBuffer& peer, int32_t port)
{
    FSocket* self = FSocket::NewLC(peer, port);
    CleanupStack::Pop( self );
    
    if (self->getLastStatus() != KErrNone) {
        // Something wrong.
        LOG.debug("FSocket::NewL - error in ConstructL (status = %d)", self->getLastStatus());
        delete self;
        return NULL;
    }
    return self;
}
void FLiveEditorListenServer::RemoveHooks()
{
	if ( Listener )
	{
		Listener->Stop();
		delete Listener;
		Listener = NULL;
	}

	if ( TransactionHistory )
	{
		delete TransactionHistory;
		TransactionHistory = NULL;
	}

	if ( !PendingClients.IsEmpty() )
	{
		FSocket *Client = NULL;
		while( PendingClients.Dequeue(Client) )
		{
			Client->Close();
		}
	}
	for ( TArray<class FSocket*>::TIterator ClientIt(Clients); ClientIt; ++ClientIt )
	{
		(*ClientIt)->Close();
	}

	delete TickObject;
	TickObject = NULL;

	delete ObjectCreateListener;
	ObjectCreateListener = NULL;

	delete ObjectDeleteListener;
	ObjectDeleteListener = NULL;

	FCoreUObjectDelegates::PostLoadMap.RemoveAll(MapLoadObserver.Get());
	FCoreUObjectDelegates::PreLoadMap.RemoveAll(MapLoadObserver.Get());
	MapLoadObserver = NULL;
}
Esempio n. 9
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."));
			}
		}
	}
}