/**
	 * Initializes the Slate Remote server with the current settings.
	 */
	void InitializeRemoteServer( )
	{
		ShutdownRemoteServer();

		USlateRemoteSettings* Settings = GetMutableDefault<USlateRemoteSettings>();

		// load settings
		bool ResaveSettings = false;

		FIPv4Endpoint ServerEndpoint;

		if (GIsEditor)
		{
			if (!FIPv4Endpoint::Parse(Settings->EditorServerEndpoint, ServerEndpoint))
			{
				if (!Settings->EditorServerEndpoint.IsEmpty())
				{
					GLog->Logf(TEXT("Warning: Invalid Slate Remote EditorServerEndpoint '%s' - binding to all local network adapters instead"), *Settings->EditorServerEndpoint);
				}

				ServerEndpoint = SLATE_REMOTE_SERVER_DEFAULT_EDITOR_ENDPOINT;
				Settings->EditorServerEndpoint = ServerEndpoint.ToText().ToString();
				ResaveSettings = true;
			}
		}
		else
		{
			if (!FIPv4Endpoint::Parse(Settings->GameServerEndpoint, ServerEndpoint))
			{
				if (!Settings->GameServerEndpoint.IsEmpty())
				{
					GLog->Logf(TEXT("Warning: Invalid Slate Remote GameServerEndpoint '%s' - binding to all local network adapters instead"), *Settings->GameServerEndpoint);
				}

				ServerEndpoint = SLATE_REMOTE_SERVER_DEFAULT_GAME_ENDPOINT;
				Settings->GameServerEndpoint = ServerEndpoint.ToText().ToString();
				ResaveSettings = true;
			}
		}

		if (ResaveSettings)
		{
			Settings->SaveConfig();
		}

		// create server
		ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);

		if (SocketSubsystem != nullptr)
		{
			RemoteServer = MakeShareable(new FSlateRemoteServer(*SocketSubsystem, ServerEndpoint));
		}
		else
		{
			GLog->Logf(TEXT("Error: SlateRemote: Failed to acquire socket subsystem."));
		}
	}
UJavascriptWebSocket* UJavascriptWebSocket::Connect(const FString& EndpointString)
{
	FIPv4Endpoint Endpoint;

	if (!FIPv4Endpoint::Parse(EndpointString, Endpoint))
	{
		return nullptr;
	}
	
	auto addr = Endpoint.ToInternetAddr();
	return CreateFrom(new FJavascriptWebSocket(*addr), GetTransientPackage());
}
	/** Initializes the message bridge with the current settings. */
	void InitializeBridge()
	{
		ShutdownBridge();

		UUdpMessagingSettings* Settings = GetMutableDefault<UUdpMessagingSettings>();
		bool ResaveSettings = false;

		FIPv4Endpoint UnicastEndpoint;
		FIPv4Endpoint MulticastEndpoint;

		if (!FIPv4Endpoint::Parse(Settings->UnicastEndpoint, UnicastEndpoint))
		{
			if (!Settings->UnicastEndpoint.IsEmpty())
			{
				GLog->Logf(TEXT("Warning: Invalid UDP Messaging UnicastEndpoint '%s' - binding to all local network adapters instead"), *Settings->UnicastEndpoint);
			}

			UnicastEndpoint = FIPv4Endpoint::Any;
			Settings->UnicastEndpoint = UnicastEndpoint.ToText().ToString();
			ResaveSettings = true;
		}

		if (!FIPv4Endpoint::Parse(Settings->MulticastEndpoint, MulticastEndpoint))
		{
			if (!Settings->MulticastEndpoint.IsEmpty())
			{
				GLog->Logf(TEXT("Warning: Invalid UDP Messaging MulticastEndpoint '%s' - using default endpoint '%s' instead"), *Settings->MulticastEndpoint, *UDP_MESSAGING_DEFAULT_MULTICAST_ENDPOINT.ToText().ToString());
			}

			MulticastEndpoint = UDP_MESSAGING_DEFAULT_MULTICAST_ENDPOINT;
			Settings->MulticastEndpoint = MulticastEndpoint.ToText().ToString();
			ResaveSettings = true;
		}

		if (Settings->MulticastTimeToLive == 0)
		{
			Settings->MulticastTimeToLive = 1;
			ResaveSettings = true;		
		}

		if (ResaveSettings)
		{
			Settings->SaveConfig();
		}

		GLog->Logf(TEXT("UdpMessaging: Initializing bridge on interface %s to multicast group %s."), *UnicastEndpoint.ToText().ToString(), *MulticastEndpoint.ToText().ToString());

		MessageBridge = FMessageBridgeBuilder()
			.UsingTransport(MakeShareable(new FUdpMessageTransport(UnicastEndpoint, MulticastEndpoint, Settings->MulticastTimeToLive)));
	}
	/** Initializes the message tunnel with the current settings. */
	void InitializeTunnel()
	{
		ShutdownTunnel();

		UUdpMessagingSettings* Settings = GetMutableDefault<UUdpMessagingSettings>();
		bool ResaveSettings = false;

		FIPv4Endpoint UnicastEndpoint;
		FIPv4Endpoint MulticastEndpoint;

		if (!FIPv4Endpoint::Parse(Settings->TunnelUnicastEndpoint, UnicastEndpoint))
		{
			GLog->Logf(TEXT("Warning: Invalid UDP Tunneling UnicastEndpoint '%s' - binding to all local network adapters instead"), *Settings->UnicastEndpoint);
			UnicastEndpoint = FIPv4Endpoint::Any;
			Settings->UnicastEndpoint = UnicastEndpoint.ToString();
			ResaveSettings = true;
		}

		if (!FIPv4Endpoint::Parse(Settings->TunnelMulticastEndpoint, MulticastEndpoint))
		{
			GLog->Logf(TEXT("Warning: Invalid UDP Tunneling MulticastEndpoint '%s' - using default endpoint '%s' instead"), *Settings->MulticastEndpoint, *UDP_MESSAGING_DEFAULT_MULTICAST_ENDPOINT.ToText().ToString());
			MulticastEndpoint = UDP_MESSAGING_DEFAULT_MULTICAST_ENDPOINT;
			Settings->MulticastEndpoint = MulticastEndpoint.ToString();
			ResaveSettings = true;
		}

		if (ResaveSettings)
		{
			Settings->SaveConfig();
		}

		GLog->Logf(TEXT("UdpMessaging: Initializing tunnel on interface %s to multicast group %s."), *UnicastEndpoint.ToText().ToString(), *MulticastEndpoint.ToText().ToString());

		MessageTunnel = MakeShareable(new FUdpMessageTunnel(UnicastEndpoint, MulticastEndpoint));

		// initiate connections
		for (int32 EndpointIndex = 0; EndpointIndex < Settings->RemoteTunnelEndpoints.Num(); ++EndpointIndex)
		{
			FIPv4Endpoint RemoteEndpoint;

			if (FIPv4Endpoint::Parse(Settings->RemoteTunnelEndpoints[EndpointIndex], RemoteEndpoint))
			{
				MessageTunnel->Connect(RemoteEndpoint);
			}
			else
			{
				GLog->Logf(TEXT("Warning: Invalid UDP RemoteTunnelEndpoint '%s' - skipping"), *Settings->RemoteTunnelEndpoints[EndpointIndex]);
			}
		}
	}
Exemple #5
0
/* Provide a dummy echo service to echo received data back for development purpose */
bool UNetworkManager::StartEchoService(FSocket* ClientSocket, const FIPv4Endpoint& ClientEndpoint)
{
	if (!this->ConnectionSocket) // Only maintain one active connection, So just reuse the TCPListener thread.
	{
		UE_LOG(LogUnrealCV, Warning, TEXT("New client connected from %s"), *ClientEndpoint.ToString());
		// ClientSocket->SetNonBlocking(false); // When this in blocking state, I can not use this socket to send message back
		ConnectionSocket = ClientSocket;

		// Listening data here or start a new thread for data?
		// Reuse the TCP Listener thread for getting data, only support one connection
		uint32 BufferSize = 1024;
		int32 Read = 0;
		TArray<uint8> ReceivedData;
		ReceivedData.SetNumZeroed(BufferSize);
		while (1)
		{
			// Easier to use raw FSocket here, need to detect remote socket disconnection
			bool RecvStatus = ClientSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);

			// if (!RecvStatus) // The connection is broken
			if (Read == 0)
			// RecvStatus == true if Read >= 0, this is used to determine client disconnection
			// -1 means no data, 0 means disconnected
			{
				ConnectionSocket = NULL; // Use this to determine whether client is connected
				return false;
			}
			int32 Sent;
			ClientSocket->Send(ReceivedData.GetData(), Read, Sent); // Echo the message back
			check(Read == Sent);
		}
		return true;
	}
	return false;
}
Exemple #6
0
/** Connected Handler */
bool UNetworkManager::Connected(FSocket* ClientSocket, const FIPv4Endpoint& ClientEndpoint)
{
	bool ServiceStatus = false;
	BroadcastConnected(*ClientEndpoint.ToString());
	// ServiceStatus = StartEchoService(ClientSocket, ClientEndpoint);
	ServiceStatus = StartMessageService(ClientSocket, ClientEndpoint);
	return ServiceStatus;
	// This is a blocking service, if need to support multiple connections, consider start a new thread here.
}
PRAGMA_DISABLE_SHADOW_VARIABLE_WARNINGS

UJavascriptWebSocket* UJavascriptWebSocket::Connect(const FString& EndpointString)
{
#if WITH_JSWEBSOCKET
	FIPv4Endpoint Endpoint;

	if (!FIPv4Endpoint::Parse(EndpointString, Endpoint))
	{
		return nullptr;
	}
	
	auto addr = Endpoint.ToInternetAddr();
	return CreateFrom(new FJavascriptWebSocket(*addr), GetTransientPackage());
#else
	return nullptr;
#endif
}
FUdpMessageBeacon::FUdpMessageBeacon(FSocket* InSocket, const FGuid& InSocketId, const FIPv4Endpoint& InMulticastEndpoint)
	: LastEndpointCount(1)
	, LastHelloSent(FDateTime::MinValue())
	, NextHelloTime(FDateTime::UtcNow())
	, NodeId(InSocketId)
	, Socket(InSocket)
	, Stopping(false)
{
	EndpointLeftEvent = FPlatformProcess::CreateSynchEvent();
	MulticastAddress = InMulticastEndpoint.ToInternetAddr();

	Thread = FRunnableThread::Create(this, TEXT("FUdpMessageBeacon"), 128 * 1024, TPri_AboveNormal, FPlatformAffinity::GetPoolThreadMask());
}
Exemple #9
0
/**
  * Start message service in listening thread
  * TODO: Start a new background thread to receive message
  */
bool UNetworkManager::StartMessageService(FSocket* ClientSocket, const FIPv4Endpoint& ClientEndpoint)
{
	if (!this->ConnectionSocket)
	{
		ConnectionSocket = ClientSocket;

		UE_LOG(LogUnrealCV, Warning, TEXT("New client connected from %s"), *ClientEndpoint.ToString());
		// ClientSocket->SetNonBlocking(false); // When this in blocking state, I can not use this socket to send message back
		FString Confirm = FString::Printf(TEXT("connected to %s"), *GetProjectName());
		bool IsSent = this->SendMessage(Confirm); // Send a hello message
		if (!IsSent)
		{
			UE_LOG(LogUnrealCV, Error, TEXT("Failed to send welcome message to client."));
		}

		// TODO: Start a new thread
		while (this->ConnectionSocket) // Listening thread, while the client is still connected
		{
			FArrayReader ArrayReader;
      bool unknown_error = false;
			if (!FSocketMessageHeader::ReceivePayload(ArrayReader, ConnectionSocket, &unknown_error))
				// Wait forever until got a message, or return false when error happened
			{
        if (unknown_error) {
          BroadcastError(FString("ReceivePayload failed with unknown error"));
        }
				this->ConnectionSocket = NULL;
				return false; // false will release the ClientSocket
				break; // Remote socket disconnected
			}

			FString Message = StringFromBinaryArray(ArrayReader);
			BroadcastReceived(Message);
			// Fire raw message received event, use message id to connect request and response
			UE_LOG(LogUnrealCV, Warning, TEXT("Receive message %s"), *Message);
		}
		return false; // TODO: What is the meaning of return value?
	}
	else
	{
		// No response and let the client silently timeout
		UE_LOG(LogUnrealCV, Warning, TEXT("Only one client is allowed, can not allow new connection from %s"), *ClientEndpoint.ToString());
		return false; // Already have a connection
	}
}
bool FSlateRemoteServer::StartServer( const FIPv4Endpoint& ServerEndpoint )
{
	ServerSocket = FUdpSocketBuilder(TEXT("SlateRemoteServerSocket"))
		.AsNonBlocking()
		.AsReusable()
		.BoundToEndpoint(ServerEndpoint);

	if (ServerSocket == nullptr)
	{
		GLog->Logf(TEXT("SlateRemoteServer: Failed to create server socket on %s"), *ServerEndpoint.ToText().ToString());

		return false;
	}

	TickDelegate = FTickerDelegate::CreateRaw(this, &FSlateRemoteServer::HandleTicker);
	TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(TickDelegate, 0.0f);

	return true;
}