diff options
Diffstat (limited to 'Runtime/Network/PlayerCommunicator/GeneralConnection.h')
| -rw-r--r-- | Runtime/Network/PlayerCommunicator/GeneralConnection.h | 266 | 
1 files changed, 266 insertions, 0 deletions
| diff --git a/Runtime/Network/PlayerCommunicator/GeneralConnection.h b/Runtime/Network/PlayerCommunicator/GeneralConnection.h new file mode 100644 index 0000000..1f253d8 --- /dev/null +++ b/Runtime/Network/PlayerCommunicator/GeneralConnection.h @@ -0,0 +1,266 @@ +#pragma once + +#if ENABLE_PLAYERCONNECTION +#define ENABLE_MULTICAST (!UNITY_FLASH) + +#include "Runtime/Serialize/SwapEndianBytes.h" +#include "Runtime/Network/MulticastSocket.h" +#include "Runtime/Network/ServerSocket.h" +#include "Runtime/Network/SocketStreams.h" + + +#if UNITY_WIN +#include <winsock2.h> +#include <ws2tcpip.h> +#elif UNITY_XENON +#include <xtl.h> +#else +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <fcntl.h> +#include <errno.h> +#endif +#include "Runtime/Profiler/TimeHelper.h" +#include "Runtime/Threads/Mutex.h" + + +// used ports: +//   MulticastPort : 54998 +//   ListenPorts : 55000 - 55511 +//   Multicast(unittests) : 55512 - 56023 + +#define ENABLE_PLAYER_CONNECTION_DEBUG_LOG 0 + +#if ENABLE_PLAYER_CONNECTION_DEBUG_LOG +#define LOG_PLAYER_CONNECTION(str) { \ +	bool oldlog = IsLogEnabled(); \ +	SetLogEnabled(false); \ +	printf_console ("[%04x] %s\n", Thread::GetCurrentThreadID(), (str).c_str()); \ +	SetLogEnabled(oldlog); \ +} +#else +#define LOG_PLAYER_CONNECTION(str) +#endif + +#if SUPPORT_THREADS +#define LOG_PLAYER_CONNECTION_CRITICAL(str) printf_console ("[%04x] %s\n", Thread::GetCurrentThreadID(), (str).c_str()) +#else +#define LOG_PLAYER_CONNECTION_CRITICAL(str) printf_console ("[] %s\n", (str).c_str()) +#endif + +#define PLAYER_MULTICAST_GROUP "225.0.0.222" +#define PLAYER_MULTICAST_PORT 54997 + +#define PLAYER_DIRECTCONNECT_PORT 54999 +#define PLAYER_DIRECTCONNECT_GUID 1337 + +#define PLAYER_DIRECT_IP_CONNECT_GUID 0xFEED + +#define PLAYER_LISTEN_PORT 55000 +#define PLAYER_UNITTEST_MULTICAST_PORT 55512 +#define PLAYER_PORT_MASK 511 +#define PLAYER_MESSAGE_MAGIC_NUMBER 0x4E8F + +#define PLAYER_CONNECTION_CONFIG_DATA_FORMAT_LISTEN "listen %u %d %d %d" +#define PLAYER_CONNECTION_CONFIG_DATA_FORMAT_LISTEN_PRINT "listen <guid> <debugging> <waitonstartup> <startprofiler>" +#define PLAYER_CONNECTION_CONFIG_DATA_FORMAT_CONNECT_LIST "connect %s %s %s %s %s %s %s %s %s %s" +#define PLAYER_CONNECTION_CONFIG_DATA_FORMAT_CONNECT "connect %s" +#define PLAYER_CONNECTION_CONFIG_DATA_FORMAT_CONNECT_PRINT "connect <ip>" + +#define SERVER_IDENTIFICATION_FORMAT "[IP] %s [Port] %lu [Flags] %lu [Guid] %lu [EditorId] %lu [Version] %d [Id] %s [Debug] %d" + + +#define ANY_PLAYERCONNECTION 0 + +bool SocketCallSucceeded(int res); + +class GeneralConnection +{ +public: +	enum MulticastFlags +	{ +		kRequestImmediateConnect = 1<<0, +		kSupportsProfile = 1<<1, +		kCustomMessage = 1<<2 +	}; + +	enum { kMulticastBufferSize = 256 }; +	enum { kDataBufferMaxSize =  8*1024*1024 }; +	enum { kDataBufferFlushThreshold =  7*1024*1024 }; + +#if ENABLE_MULTICAST +	// Parsed struct from a buffer that contains all the information sent by the player to the editor +	// Used for showing a list of all available profilers and performing autoconnect on the profiler +	struct MulticastInfo +	{ +		MulticastInfo(); + +		bool Parse (const char* buffer, void* in = NULL); + +		bool IsValid () const { return m_Valid; } +		bool IsLocalhost() const { return m_IsLocalhost; } + +		UInt32 GetGuid () const { return m_Guid; } +		UInt32 GetEditorGuid () const { return m_EditorGuid; } + +		UInt32 GetPort () const { return m_Port; } +		std::string const& GetIP () const { return m_Ip; } + +		bool ImmediateConnect() const { return (m_Flags & kRequestImmediateConnect) != 0; } +		bool HasCustomMessage() const { return (m_Flags & kCustomMessage) != 0; } +		bool HasProfiler() const { return (m_Flags & kSupportsProfile) != 0; } + +		std::string const& GetIdentifier() const { return m_Identifier; } +	private: + +		void Clear (); +		void SetLocalhostFlag(); + +		std::string m_Buffer; +		std::string m_Ip; +		UInt32 m_Port; +		UInt32 m_Flags; +		UInt32 m_Guid; +		UInt32 m_EditorGuid; +		std::string m_Identifier; +		bool m_Valid; +		bool m_IsLocalhost; +	}; +#endif + +	enum MessageID{ +		// messageID 1 - 31 reserved for (future) internal use +		kProfileDataMessage             = 32, +		kProfileStartupInformation      = 33, + +		kObjectMemoryProfileSnapshot    = 40, //request the memory profile +		kObjectMemoryProfileDataMessage = 41, //send the object memory profile + +		kLogMessage                     = 100, +		kCleanLogMessage                = 101, + +		kFileTransferMessage            = 200, +		kFileReadyMessage               = 201, +		kCaptureHeaphshotMessage        = 202, + +		kPingAliveMessage               = 300, +		kApplicationQuitMessage         = 301, +		kLastMessageID, +	}; + +	struct NetworkMessage +	{ +		void InitializeMessage(); +		bool CheckMessageValidity(); +		void SetID (MessageID id); +		MessageID GetID (); +		void SetDataSize (UInt32 size); +		UInt32 GetDataSize (); + +		bool AllowSkip(){return m_ID == kProfileDataMessage;} + +	private: +		UInt16 m_MagicNumber; // in little endian +		UInt16 m_ID; // in little endian +		UInt32 m_Size; // in little endian +	}; + +	struct Connection +	{ +	public: +		Connection(TSocketHandle socketHandle); +		~Connection(); + +		bool IsValid() const { return m_SocketStream.IsConnected(); }; +		bool Poll() { return m_SocketStream.Poll(5); } +		bool HasBytesToSend() const { return m_SocketStream.SendBuffer().GetAvailableSize() > 0; } +		const void* ReceiveMessage(NetworkMessage* message); +		void ReleaseReceivedMessage(); +		void SendMessage(NetworkMessage& message, const void* data); + +		UInt32 GetSendBufferSize() const { return m_SocketStream.SendBuffer().GetAllocatedSize(); } +		UInt32 GetRecvBufferSize() const { return m_SocketStream.RecvBuffer().GetAllocatedSize(); } + +	private: +		Mutex					m_SendMutex; +		Mutex					m_RecvMutex; +		NetworkMessage			m_PendingMessage; +		void*					m_PendingMessageData; +		bool					m_LocallyAllocatedMessageData; +		bool					m_HasPendingMessage; +#if UNITY_FLASH +		BufferedSocketStream	m_SocketStream; +#elif UNITY_WINRT +		BufferedSocketStream m_SocketStream; +#else +		ThreadedSocketStream	m_SocketStream; +#endif +	}; + +	virtual ~GeneralConnection (); + +	bool IsConnected () { return !m_Connections.empty(); } +	void SetLogEnabled (bool v) { m_LogEnabled = v; } +	bool IsLogEnabled () const { return m_LogEnabled; } +	void DisconnectAll (); + +	void SendMessage (UInt32 guid, MessageID id, const void* data, UInt32 size); + +	typedef void (*MessageHandlerFunc) (const void* data, UInt32 size, UInt32 guid); +	void RegisterMessageHandler (MessageID messageID, MessageHandlerFunc func); +	void UnregisterMessageHandler (MessageID messageID, MessageHandlerFunc func); + +	typedef void (*ConnectionHandlerFunc) (UInt32 guid); +	void RegisterDisconnectionHandler( ConnectionHandlerFunc func ); +	void RegisterConnectionHandler( ConnectionHandlerFunc func ); +	void UnregisterDisconnectionHandler( ConnectionHandlerFunc func ); +	void UnregisterConnectionHandler( ConnectionHandlerFunc func ); + +	virtual void WaitForFinish(); + +	UInt32 GetLocalGuid() const; + +	static void RunningUnitTest() { ms_RunningUnitTests = true;} + +protected: +	GeneralConnection (); + +	bool HasBytesToSend() const; + +	static void Initialize (); +	static void Cleanup (); + +	void RegisterConnection (UInt32 guid, TSocketHandle socketHandle); +	void Disconnect (UInt32 guid); + +	Connection* GetConnection(UInt32 guid); + +	virtual bool IsServer () = 0; + +	void Poll (); + +protected: +	std::string m_LocalIP; + +#if ENABLE_MULTICAST +	MulticastSocket m_MulticastSocket; +#endif + +	typedef std::map< int, Connection* > ConnectionMap; +	ConnectionMap m_Connections; + +	std::map< MessageID, MessageHandlerFunc > m_HandlerMap; +	std::vector< ConnectionHandlerFunc > m_ConnectionHandlers; +	std::vector< ConnectionHandlerFunc > m_DisconnectionHandlers; + +	UInt32 m_LocalGuid; + +	bool m_LogEnabled; + +	static bool ms_RunningUnitTests; +	static int ms_Version; +}; + +#endif // ENABLE_PLAYERCONNECTION | 
