diff --git a/capture/src/capture.cpp b/capture/src/capture.cpp index ff833f739a..9f9bbe3768 100644 --- a/capture/src/capture.cpp +++ b/capture/src/capture.cpp @@ -113,7 +113,7 @@ int main( int argc, char** argv ) const char* output = nullptr; int port = 8086; int seconds = -1; - int64_t memoryLimit = -1; + int64_t memoryLimit = tracy::NO_WORKER_MEMORY_LIMIT; int c; while( ( c = getopt( argc, argv, "a:o:p:fs:m:" ) ) != -1 ) diff --git a/cmake/server.cmake b/cmake/server.cmake index c12a340842..34d100652a 100644 --- a/cmake/server.cmake +++ b/cmake/server.cmake @@ -17,6 +17,7 @@ set(TRACY_SERVER_SOURCES TracyMemory.cpp TracyMmap.cpp TracyPrint.cpp + TracyProtocolServer.cpp TracySysUtil.cpp TracyTaskDispatch.cpp TracyTextureCompression.cpp diff --git a/profiler/src/main.cpp b/profiler/src/main.cpp index 8292a692a1..fb9ac18406 100644 --- a/profiler/src/main.cpp +++ b/profiler/src/main.cpp @@ -46,6 +46,7 @@ #include "../../server/tracy_robin_hood.h" #include "../../server/TracyFileHeader.hpp" #include "../../server/TracyFileRead.hpp" +#include "../../server/TracyProtocolServer.hpp" #include "../../server/TracyPrint.hpp" #include "../../server/TracySysUtil.hpp" #include "../../server/TracyWorker.hpp" @@ -85,7 +86,7 @@ enum class ViewShutdown { False, True, Join }; static tracy::unordered_flat_map clients; static std::unique_ptr view; static tracy::BadVersionState badVer; -static uint16_t port = 8086; +static uint16_t port = tracy::DEFAULT_BROADCAST_UDP_PORT; static const char* connectTo = nullptr; static char title[128]; static std::thread loadThread, updateThread, updateNotesThread; @@ -452,76 +453,15 @@ static void UpdateBroadcastClients() { auto msg = broadcastListen->Read( len, addr, 0 ); if( !msg ) break; - if( len > sizeof( tracy::BroadcastMessage ) ) continue; - uint16_t broadcastVersion; - memcpy( &broadcastVersion, msg, sizeof( uint16_t ) ); - if( broadcastVersion <= tracy::BroadcastVersion ) + auto parsedMessageOpt = tracy::ParseBroadcastMessage(msg, len); + if (parsedMessageOpt.has_value()) { - uint32_t protoVer; - char procname[tracy::WelcomeMessageProgramNameSize]; - int32_t activeTime; - uint16_t listenPort; - uint64_t pid; - - switch( broadcastVersion ) - { - case 3: - { - tracy::BroadcastMessage bm; - memcpy( &bm, msg, len ); - protoVer = bm.protocolVersion; - strcpy( procname, bm.programName ); - activeTime = bm.activeTime; - listenPort = bm.listenPort; - pid = bm.pid; - break; - } - case 2: - { - if( len > sizeof( tracy::BroadcastMessage_v2 ) ) continue; - tracy::BroadcastMessage_v2 bm; - memcpy( &bm, msg, len ); - protoVer = bm.protocolVersion; - strcpy( procname, bm.programName ); - activeTime = bm.activeTime; - listenPort = bm.listenPort; - pid = 0; - break; - } - case 1: - { - if( len > sizeof( tracy::BroadcastMessage_v1 ) ) continue; - tracy::BroadcastMessage_v1 bm; - memcpy( &bm, msg, len ); - protoVer = bm.protocolVersion; - strcpy( procname, bm.programName ); - activeTime = bm.activeTime; - listenPort = bm.listenPort; - pid = 0; - break; - } - case 0: - { - if( len > sizeof( tracy::BroadcastMessage_v0 ) ) continue; - tracy::BroadcastMessage_v0 bm; - memcpy( &bm, msg, len ); - protoVer = bm.protocolVersion; - strcpy( procname, bm.programName ); - activeTime = bm.activeTime; - listenPort = 8086; - pid = 0; - break; - } - default: - assert( false ); - break; - } - + auto parsedMessage = parsedMessageOpt.value(); auto address = addr.GetText(); + const auto clientId = tracy::ClientUniqueID(addr, parsedMessage.listenPort); const auto ipNumerical = addr.GetNumber(); - const auto clientId = uint64_t( ipNumerical ) | ( uint64_t( listenPort ) << 32 ); auto it = clients.find( clientId ); - if( activeTime >= 0 ) + if( parsedMessage.activeTime >= 0 ) { if( it == clients.end() ) { @@ -538,16 +478,24 @@ static void UpdateBroadcastClients() } ); } resolvLock.unlock(); - clients.emplace( clientId, ClientData { time, protoVer, activeTime, listenPort, pid, procname, std::move( ip ) } ); + clients.emplace(clientId, + ClientData{time, + parsedMessage.protocolVersion, + parsedMessage.activeTime, + parsedMessage.listenPort, + parsedMessage.pid, + parsedMessage.programName, + std::move(ip)}); } else { it->second.time = time; - it->second.activeTime = activeTime; - it->second.port = listenPort; - it->second.pid = pid; - it->second.protocolVersion = protoVer; - if( strcmp( it->second.procName.c_str(), procname ) != 0 ) it->second.procName = procname; + it->second.activeTime = parsedMessage.activeTime; + it->second.port = parsedMessage.listenPort; + it->second.pid = parsedMessage.pid; + it->second.protocolVersion = parsedMessage.protocolVersion; + if (strcmp(it->second.procName.c_str(), parsedMessage.programName) != 0) + it->second.procName = parsedMessage.programName; } } else if( it != clients.end() ) diff --git a/profiler/src/profiler/TracyView.cpp b/profiler/src/profiler/TracyView.cpp index bdeb7d720c..f07b715f80 100644 --- a/profiler/src/profiler/TracyView.cpp +++ b/profiler/src/profiler/TracyView.cpp @@ -36,7 +36,7 @@ namespace tracy double s_time = 0; View::View( void(*cbMainThread)(const std::function&, bool), const char* addr, uint16_t port, ImFont* fixedWidth, ImFont* smallFont, ImFont* bigFont, SetTitleCallback stcb, SetScaleCallback sscb, AttentionCallback acb, const Config& config, AchievementsMgr* amgr ) - : m_worker( addr, port, config.memoryLimit == 0 ? -1 : ( config.memoryLimitPercent * tracy::GetPhysicalMemorySize() / 100 ) ) + : m_worker( addr, port, config.memoryLimit == 0 ? NO_WORKER_MEMORY_LIMIT : ( config.memoryLimitPercent * tracy::GetPhysicalMemorySize() / 100 ) ) , m_staticView( false ) , m_viewMode( ViewMode::LastFrames ) , m_viewModeHeuristicTry( true ) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 80fe1561b6..2ad0a6b5fb 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1629,12 +1629,12 @@ void Profiler::Worker() auto dataPort = m_userPort != 0 ? m_userPort : TRACY_DATA_PORT; #else const bool dataPortSearch = m_userPort == 0; - auto dataPort = m_userPort != 0 ? m_userPort : 8086; + auto dataPort = m_userPort != 0 ? m_userPort : DEFAULT_CLIENT_DATA_TCP_PORT; #endif #ifdef TRACY_BROADCAST_PORT const auto broadcastPort = TRACY_BROADCAST_PORT; #else - const auto broadcastPort = 8086; + const auto broadcastPort = DEFAULT_BROADCAST_UDP_PORT; #endif while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); diff --git a/public/common/TracyProtocol.hpp b/public/common/TracyProtocol.hpp index ad90a7ad7b..e92ed06681 100644 --- a/public/common/TracyProtocol.hpp +++ b/public/common/TracyProtocol.hpp @@ -7,6 +7,9 @@ namespace tracy { +constexpr uint16_t DEFAULT_BROADCAST_UDP_PORT = 8086; +constexpr uint16_t DEFAULT_CLIENT_DATA_TCP_PORT = 8086; + constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; } enum : uint32_t { ProtocolVersion = 68 }; diff --git a/public/common/TracySocket.cpp b/public/common/TracySocket.cpp index bdba361965..25ee062402 100644 --- a/public/common/TracySocket.cpp +++ b/public/common/TracySocket.cpp @@ -651,7 +651,7 @@ void IpAddress::Set( const struct sockaddr& addr ) #else auto ai = (const struct sockaddr_in*)&addr; #endif - inet_ntop( AF_INET, &ai->sin_addr, m_text, 17 ); + inet_ntop(AF_INET, &ai->sin_addr, m_text, TEXT_SIZE); m_number = ai->sin_addr.s_addr; } diff --git a/public/common/TracySocket.hpp b/public/common/TracySocket.hpp index f7713aac66..d3cbcb405b 100644 --- a/public/common/TracySocket.hpp +++ b/public/common/TracySocket.hpp @@ -112,6 +112,8 @@ class UdpBroadcast class IpAddress { public: + static constexpr size_t TEXT_SIZE = 17; + IpAddress(); ~IpAddress(); @@ -127,7 +129,7 @@ class IpAddress private: uint32_t m_number; - char m_text[17]; + char m_text[TEXT_SIZE]; }; class UdpListen diff --git a/server/TracyProtocolServer.cpp b/server/TracyProtocolServer.cpp new file mode 100644 index 0000000000..816e92fb00 --- /dev/null +++ b/server/TracyProtocolServer.cpp @@ -0,0 +1,107 @@ +#include "TracyProtocolServer.hpp" +#include +#include +#include + +namespace tracy +{ +std::optional ParseBroadcastMessage(const char* msg, size_t msgLen) +{ + if (msgLen < sizeof(uint16_t)) + { + std::cout << "Received too short broadcast message" << std::endl; + return std::nullopt; + } + uint16_t broadcastVersion; + memcpy(&broadcastVersion, msg, sizeof(uint16_t)); + if (broadcastVersion > tracy::BroadcastVersion) + { + std::cout << "Received broadcast message with unsupported version: " << broadcastVersion << std::endl; + return std::nullopt; + } + switch (broadcastVersion) + { + case 3: + { + if (msgLen > sizeof(tracy::BroadcastMessage)) + { + std::cout << "Received unexpected size broadcast v3 message" << std::endl; + return std::nullopt; + } + tracy::BroadcastMessage bm; + memcpy(&bm, msg, msgLen); + return bm; + break; + } + case 2: + { + if (msgLen > sizeof(tracy::BroadcastMessage_v2)) + { + std::cout << "Received unexpected size broadcast v2 message" << std::endl; + return std::nullopt; + } + tracy::BroadcastMessage_v2 bm; + memcpy(&bm, msg, msgLen); + + tracy::BroadcastMessage out; + out.broadcastVersion = broadcastVersion; + out.protocolVersion = bm.protocolVersion; + out.activeTime = bm.activeTime; + out.listenPort = bm.listenPort; + strcpy(out.programName, bm.programName); + out.pid = 0; + return out; + break; + } + case 1: + { + if (msgLen > sizeof(tracy::BroadcastMessage_v1)) + { + std::cout << "Received unexpected size broadcast v1 message" << std::endl; + return std::nullopt; + } + tracy::BroadcastMessage_v1 bm; + memcpy(&bm, msg, msgLen); + + tracy::BroadcastMessage out; + out.broadcastVersion = broadcastVersion; + out.protocolVersion = bm.protocolVersion; + out.activeTime = bm.activeTime; + out.listenPort = bm.listenPort; + strcpy(out.programName, bm.programName); + out.pid = 0; + return out; + break; + } + case 0: + { + if (msgLen > sizeof(tracy::BroadcastMessage_v0)) + { + std::cout << "Received unexpected size broadcast v0 message" << std::endl; + return std::nullopt; + } + tracy::BroadcastMessage_v0 bm; + memcpy(&bm, msg, msgLen); + + tracy::BroadcastMessage out; + out.broadcastVersion = broadcastVersion; + out.protocolVersion = bm.protocolVersion; + out.activeTime = bm.activeTime; + out.listenPort = tracy::DEFAULT_CLIENT_DATA_TCP_PORT; + strcpy(out.programName, bm.programName); + out.pid = 0; + return out; + break; + } + default: + assert(false); + break; + } + return std::nullopt; +} + +uint64_t ClientUniqueID(tracy::IpAddress const& addr, uint16_t port) +{ + return uint64_t(addr.GetNumber()) | (uint64_t(port) << 32); +} +} // namespace tracy diff --git a/server/TracyProtocolServer.hpp b/server/TracyProtocolServer.hpp new file mode 100644 index 0000000000..09f5457d10 --- /dev/null +++ b/server/TracyProtocolServer.hpp @@ -0,0 +1,17 @@ +// server-side functions supporting the protocol +#ifndef __TRACYPROTOCOLSERVER_HPP__ +#define __TRACYPROTOCOLSERVER_HPP__ + +#include +#include "TracyProtocol.hpp" +#include "TracySocket.hpp" + +namespace tracy +{ +// create the latest version of broadcast message, migrating older versions if possible +std::optional ParseBroadcastMessage(const char* msg, size_t msgLen); +// internal unique ID for a client +uint64_t ClientUniqueID(tracy::IpAddress const& addr, uint16_t port); +} // namespace tracy + +#endif diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 5c2972914c..c1281963af 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -318,7 +318,7 @@ Worker::Worker( const char* name, const char* program, const std::vectorcalibratedGpuTime = gpuTime; ctx->calibratedCpuTime = TscTime( ev.cpuTime ); } - + void Worker::ProcessGpuTimeSync( const QueueGpuTimeSync& ev ) { auto ctx = m_gpuCtxMap[ev.context]; diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 0a4ca8292c..53e4d85a3b 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -52,6 +52,8 @@ namespace EventType }; } +constexpr int64_t NO_WORKER_MEMORY_LIMIT = -1; // anything <0 would do + struct UnsupportedVersion : public std::exception { UnsupportedVersion( int version ) : version( version ) {}