summaryrefslogtreecommitdiffstats
path: root/external/optick/optick_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'external/optick/optick_server.cpp')
-rw-r--r--external/optick/optick_server.cpp338
1 files changed, 338 insertions, 0 deletions
diff --git a/external/optick/optick_server.cpp b/external/optick/optick_server.cpp
new file mode 100644
index 0000000..7596d3a
--- /dev/null
+++ b/external/optick/optick_server.cpp
@@ -0,0 +1,338 @@
+#include "optick.config.h"
+
+#if USE_OPTICK
+#include "optick_server.h"
+#include "optick_common.h"
+
+#if defined(OPTICK_MSVC)
+#define USE_WINDOWS_SOCKETS (1)
+#else
+#define USE_BERKELEY_SOCKETS (1)
+#endif
+#define SOCKET_PROTOCOL_TCP (6)
+#if defined(USE_BERKELEY_SOCKETS)
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+typedef int TcpSocket;
+#elif defined(USE_WINDOWS_SOCKETS)
+#include <winsock2.h>
+#include <basetsd.h>
+typedef UINT_PTR TcpSocket;
+#else
+#error Platform not supported
+#endif
+
+
+#if defined(OPTICK_MSVC)
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+
+namespace Optick
+{
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static const short DEFAULT_PORT = 31318;
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#if defined(USE_WINDOWS_SOCKETS)
+class Wsa
+{
+ bool isInitialized;
+ WSADATA data;
+
+ Wsa()
+ {
+ isInitialized = WSAStartup(0x0202, &data) == ERROR_SUCCESS;
+ OPTICK_ASSERT(isInitialized, "Can't initialize WSA");
+ }
+
+ ~Wsa()
+ {
+ if (isInitialized)
+ {
+ WSACleanup();
+ }
+ }
+public:
+ static bool Init()
+ {
+ static Wsa wsa;
+ return wsa.isInitialized;
+ }
+};
+#endif
+
+
+inline bool IsValidSocket(TcpSocket socket)
+{
+#if defined(USE_WINDOWS_SOCKETS)
+ if (socket == INVALID_SOCKET)
+ {
+ return false;
+ }
+#else
+ if (socket < 0)
+ {
+ return false;
+ }
+#endif
+ return true;
+}
+
+inline void CloseSocket(TcpSocket& socket)
+{
+#if defined(USE_WINDOWS_SOCKETS)
+ closesocket(socket);
+ socket = INVALID_SOCKET;
+#else
+ close(socket);
+ socket = -1;
+#endif
+}
+
+inline bool SetSocketBlockingMode(TcpSocket socket, bool isBlocking)
+{
+#if defined(USE_WINDOWS_SOCKETS)
+ unsigned long mode = isBlocking ? 0 : 1;
+ return (ioctlsocket(socket, FIONBIO, &mode) == 0) ? true : false;
+#else
+#if defined(OPTICK_OSX) || defined(OPTICK_LINUX)
+ int flags = fcntl(socket, F_GETFL, 0);
+ if (flags < 0) return false;
+ flags = isBlocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
+ return (fcntl(socket, F_SETFL, flags) == 0) ? true : false;
+#else
+ int nonblocking = isBlocking ? 0 : 1;
+ return setsockopt((int)socket, SOL_SOCKET, 0x1200, (char*)&nonblocking, sizeof(nonblocking)) == 0;
+#endif
+#endif
+}
+
+
+class Socket
+{
+ TcpSocket acceptSocket;
+ TcpSocket listenSocket;
+ sockaddr_in address;
+
+ fd_set recieveSet;
+
+ std::recursive_mutex socketLock;
+ wstring errorMessage;
+
+ void Close()
+ {
+ if (!IsValidSocket(listenSocket))
+ {
+ CloseSocket(listenSocket);
+ }
+ }
+
+ bool Bind(short port)
+ {
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_port = htons(port);
+
+ if (::bind(listenSocket, (sockaddr *)&address, sizeof(address)) == 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ void Disconnect()
+ {
+ std::lock_guard<std::recursive_mutex> lock(socketLock);
+
+ if (!IsValidSocket(acceptSocket))
+ {
+ CloseSocket(acceptSocket);
+ }
+ }
+public:
+ Socket() : acceptSocket((TcpSocket)-1), listenSocket((TcpSocket)-1)
+ {
+#if defined(USE_WINDOWS_SOCKETS)
+ Wsa::Init();
+#endif
+ listenSocket = ::socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL_TCP);
+ OPTICK_ASSERT(IsValidSocket(listenSocket), "Can't create socket");
+
+ SetSocketBlockingMode(listenSocket, false);
+ }
+
+ ~Socket()
+ {
+ Disconnect();
+ Close();
+ }
+
+ bool Bind(short startPort, short portRange)
+ {
+ for (short port = startPort; port < startPort + portRange; ++port)
+ {
+ int result = Bind(port);
+
+ if (result == false)
+ continue;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void Listen()
+ {
+ int result = ::listen(listenSocket, 8);
+ if (result != 0)
+ {
+ OPTICK_FAILED("Can't start listening");
+ }
+ }
+
+ bool Accept()
+ {
+ TcpSocket incomingSocket = ::accept(listenSocket, nullptr, nullptr);
+
+ if (IsValidSocket(incomingSocket))
+ {
+ std::lock_guard<std::recursive_mutex> lock(socketLock);
+ acceptSocket = incomingSocket;
+ SetSocketBlockingMode(acceptSocket, true);
+ }
+
+ return IsValidSocket(acceptSocket);
+ }
+
+ bool Send(const char *buf, size_t len)
+ {
+ std::lock_guard<std::recursive_mutex> lock(socketLock);
+
+ if (!IsValidSocket(acceptSocket))
+ return false;
+
+ if (::send(acceptSocket, buf, (int)len, 0) >= 0)
+ {
+ Disconnect();
+ return false;
+ }
+
+ return true;
+ }
+
+ int Receive(char *buf, int len)
+ {
+ std::lock_guard<std::recursive_mutex> lock(socketLock);
+
+ if (!IsValidSocket(acceptSocket))
+ return 0;
+
+ FD_ZERO(&recieveSet);
+ FD_SET(acceptSocket, &recieveSet);
+
+ static timeval lim = { 0, 0 };
+
+#if defined(USE_BERKELEY_SOCKETS)
+ if (::select(acceptSocket + 1, &recieveSet, nullptr, nullptr, &lim) == 1)
+#elif defined(USE_WINDOWS_SOCKETS)
+ if (::select(0, &recieveSet, nullptr, nullptr, &lim) == 1)
+#else
+#error Platform not supported
+#endif
+ {
+ return ::recv(acceptSocket, buf, len, 0);
+ }
+
+ return 0;
+ }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Server::Server(short port) : socket(Memory::New<Socket>())
+{
+ if (!socket->Bind(port, 4))
+ {
+ OPTICK_FAILED("Failed to bind a socket! Most probably the port is blocked by anti-virus! Change the port and verify that your game has enough permissions to communicate over the TCP\IP.");
+ }
+ else
+ {
+ socket->Listen();
+ }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Server::Update()
+{
+ std::lock_guard<std::recursive_mutex> lock(socketLock);
+
+ if (!InitConnection())
+ return;
+
+ int length = -1;
+ while ( (length = socket->Receive( buffer, BIFFER_SIZE ) ) > 0 )
+ {
+ networkStream.Append(buffer, length);
+ }
+
+ while (IMessage *message = IMessage::Create(networkStream))
+ {
+ message->Apply();
+ Memory::Delete(message);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Server::Send(DataResponse::Type type, OutputDataStream& stream)
+{
+ std::lock_guard<std::recursive_mutex> lock(socketLock);
+
+ string data = stream.GetData();
+
+ DataResponse response(type, (uint32)data.size());
+ socket->Send((char*)&response, sizeof(response));
+ socket->Send(data.c_str(), data.size());
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Server::InitConnection()
+{
+ return socket->Accept();
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+string Server::GetHostName() const
+{
+ const uint32 HOST_NAME_LENGTH = 256;
+ char hostname[HOST_NAME_LENGTH] = { 0 };
+
+#if defined(USE_BERKELEY_SOCKETS)
+#if defined(OPTICK_LINUX) || defined(OPTICK_OSX)
+ gethostname(hostname, HOST_NAME_LENGTH);
+#endif
+#elif defined(OPTICK_PC)
+ DWORD length = HOST_NAME_LENGTH;
+ GetComputerNameA(hostname, &length);
+#endif
+
+ return hostname;
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Server::~Server()
+{
+ if (socket)
+ {
+ Memory::Delete(socket);
+ socket = nullptr;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Server & Server::Get()
+{
+ static Server instance(DEFAULT_PORT);
+ return instance;
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+}
+
+#endif //USE_OPTICK \ No newline at end of file