diff --git a/common/TracySocket.cpp b/common/TracySocket.cpp new file mode 100755 index 00000000..1122a1f7 --- /dev/null +++ b/common/TracySocket.cpp @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include + +#include "TracySocket.hpp" + +#ifdef _MSC_VER +# include +# include +#else +# include +# include +# include +#endif + +namespace tracy +{ + +#ifdef _MSC_VER +static bool initDone = false; +static void InitWinSock() +{ + if( !initDone ) + { + initDone = true; + WSADATA wsaData; + if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 ) + { + fprintf( stderr, "Cannot init winsock.\n" ); + exit( 1 ); + } + } +} +#endif + +Socket::Socket() + : m_sock( -1 ) +{ +#ifdef _MSC_VER + InitWinSock(); +#endif +} + +Socket::Socket( int sock ) + : m_sock( sock ) +{ +#ifdef _MSC_VER + assert( initDone ); +#endif +} + +Socket::~Socket() +{ + if( m_sock != -1 ) + { + Close(); + } +} + +bool Socket::Connect( const char* addr, const char* port ) +{ + assert( m_sock == -1 ); + + struct addrinfo hints; + struct addrinfo *res, *ptr; + + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if( getaddrinfo( addr, port, &hints, &res ) != 0 ) return false; + int sock; + for( ptr = res; ptr; ptr = ptr->ai_next ) + { + if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue; + if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 ) + { +#ifdef _MSC_VER + closesocket( sock ); +#else + close( sock ); +#endif + continue; + } + break; + } + freeaddrinfo( res ); + if( !ptr ) return false; + + m_sock = sock; + return true; +} + +void Socket::Close() +{ + assert( m_sock != -1 ); +#ifdef _MSC_VER + closesocket( m_sock ); +#else + close( m_sock ); +#endif + m_sock = -1; +} + +int Socket::Send( const void* _buf, int len ) +{ + auto buf = (const char*)_buf; + assert( m_sock != -1 ); + auto start = buf; + while( len > 0 ) + { + auto ret = send( m_sock, buf, len, 0 ); + if( ret == -1 ) return -1; + len -= ret; + buf += ret; + } + return buf - start; +} + +int Socket::Recv( void* _buf, int len ) +{ + auto buf = (char*)_buf; + assert( m_sock != -1 ); + int size; + do + { + size = recv( m_sock, buf, len, 0 ); + } + while( size == -1 ); + return size; +} + + +ListenSocket::ListenSocket() + : m_sock( -1 ) +{ +#ifdef _MSC_VER + InitWinSock(); +#endif +} + +ListenSocket::~ListenSocket() +{ +} + +bool ListenSocket::Listen( const char* port, int backlog ) +{ + assert( m_sock == -1 ); + + struct addrinfo* res; + struct addrinfo hints; + + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( nullptr, port, &hints, &res ) != 0 ) return false; + + m_sock = socket( res->ai_family, res->ai_socktype, res->ai_protocol ); +#ifdef _MSC_VER + DWORD val = 0; + setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) ); +#endif + if( bind( m_sock, res->ai_addr, res->ai_addrlen ) == -1 ) return false; + if( listen( m_sock, backlog ) == -1 ) return false; + return true; +} + +std::unique_ptr ListenSocket::Accept() +{ + struct sockaddr_storage remote; + socklen_t sz = sizeof( remote ); + + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 10000; + + fd_set fds; + FD_ZERO( &fds ); + FD_SET( m_sock, &fds ); + + select( m_sock+1, &fds, nullptr, nullptr, &tv ); + if( FD_ISSET( m_sock, &fds ) ) + { + int sock = accept( m_sock, (sockaddr*)&remote, &sz); + if( sock == -1 ) + { + return nullptr; + } + else + { + return std::make_unique( sock ); + } + } + else + { + return nullptr; + } +} + +void ListenSocket::Close() +{ + assert( m_sock != -1 ); +#ifdef _MSC_VER + closesocket( m_sock ); +#else + close( m_sock ); +#endif + m_sock = -1; +} + +} diff --git a/common/TracySocket.hpp b/common/TracySocket.hpp new file mode 100755 index 00000000..099f66cb --- /dev/null +++ b/common/TracySocket.hpp @@ -0,0 +1,52 @@ +#ifndef __TRACYSOCKET_HPP__ +#define __TRACYSOCKET_HPP__ + +#include + +namespace tracy +{ + +class Socket +{ +public: + Socket(); + Socket( int sock ); + ~Socket(); + + bool Connect( const char* addr, const char* port ); + void Close(); + + int Send( const void* buf, int len ); + int Recv( void* buf, int len ); + + Socket( const Socket& ) = delete; + Socket( Socket&& ) = delete; + Socket& operator=( const Socket& ) = delete; + Socket& operator=( Socket&& ) = delete; + +private: + int m_sock; +}; + +class ListenSocket +{ +public: + ListenSocket(); + ~ListenSocket(); + + bool Listen( const char* port, int backlog ); + std::unique_ptr Accept(); + void Close(); + + ListenSocket( const ListenSocket& ) = delete; + ListenSocket( ListenSocket&& ) = delete; + ListenSocket& operator=( const ListenSocket& ) = delete; + ListenSocket& operator=( ListenSocket&& ) = delete; + +private: + int m_sock; +}; + +} + +#endif