summaryrefslogblamecommitdiffstats
path: root/external/optick/optick_message.cpp
blob: b421d500e52f5e7161aabb3523829e74916d124e (plain) (tree)











































































































































































                                                                                                                                                              
#include "optick.config.h"

#if USE_OPTICK
#include "optick_common.h"
#include "optick_core.h"
#include "optick_message.h"
#include "optick_server.h"

namespace Optick
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct MessageHeader
{
	uint32 mark;
	uint32 length;

	static const uint32 MESSAGE_MARK = 0xB50FB50F;

	bool IsValid() const { return mark == MESSAGE_MARK; }

	MessageHeader() : mark(0), length(0) {}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class MessageFactory
{
	typedef IMessage* (*MessageCreateFunction)(InputDataStream& str);
	MessageCreateFunction factory[IMessage::COUNT];

	template<class T>
	void RegisterMessage()
	{
		factory[T::GetMessageType()] = T::Create;
	}

	MessageFactory()
	{
		memset(&factory[0], 0, sizeof(MessageCreateFunction));

		RegisterMessage<StartMessage>();
		RegisterMessage<StopMessage>();
		RegisterMessage<CancelMessage>();
		RegisterMessage<TurnSamplingMessage>();

		for (uint32 msg = 0; msg < IMessage::COUNT; ++msg)
		{
			OPTICK_ASSERT(factory[msg] != nullptr, "Message is not registered to factory");
		}
	}
public:
	static MessageFactory& Get()
	{
		static MessageFactory instance;
		return instance;
	}

	IMessage* Create(InputDataStream& str)
	{
		MessageHeader header;
		str.Read(header);

		size_t length = str.Length();

		uint16 applicationID = 0;
		uint16 messageType = IMessage::COUNT;

		str >> applicationID;
		str >> messageType;

		OPTICK_VERIFY( 0 <= messageType && messageType < IMessage::COUNT && factory[messageType] != nullptr, "Unknown message type!", return nullptr )

		IMessage* result = factory[messageType](str);

		if (header.length + str.Length() != length)
		{
			OPTICK_FAILED("Message Stream is corrupted! Invalid Protocol?")
			return nullptr;
		}

		return result;
	}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
OutputDataStream& operator<<(OutputDataStream& os, const DataResponse& val)
{
	return os << val.version << (uint32)val.type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

IMessage* IMessage::Create(InputDataStream& str)
{
	MessageHeader header;

	while (str.Peek(header))
	{
		if (header.IsValid())
		{
			if (str.Length() < header.length + sizeof(MessageHeader))
				break; // Not enough data yet

			return MessageFactory::Get().Create(str);
		} 
		else
		{
			// Some garbage in the stream?
			str.Skip(1);
		}
	}

	return nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void StartMessage::Apply()
{
	Core& core = Core::Get();
	core.SetSettings(settings);
	core.StartCapture();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IMessage* StartMessage::Create(InputDataStream& stream)
{
	StartMessage* msg = Memory::New<StartMessage>();
	CaptureSettings& settings = msg->settings;
	stream	>> settings.mode
			>> settings.categoryMask
			>> settings.samplingFrequency
			>> settings.frameLimit
			>> settings.timeLimitUs
			>> settings.spikeLimitUs
			>> settings.memoryLimitMb;
	string password;
	stream >> settings.password;
	settings.password = base64_decode(password);
	return msg;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void StopMessage::Apply()
{
	Core::Get().DumpCapture();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IMessage* StopMessage::Create(InputDataStream&)
{
	return Memory::New<StopMessage>();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CancelMessage::Apply()
{
	Core::Get().CancelCapture();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IMessage* CancelMessage::Create(InputDataStream&)
{
	return Memory::New<CancelMessage>();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IMessage* TurnSamplingMessage::Create( InputDataStream& stream )
{
	TurnSamplingMessage* msg = Memory::New<TurnSamplingMessage>();
	stream >> msg->index;
	stream >> msg->isSampling;
	return msg;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void TurnSamplingMessage::Apply()
{
	// Backward compatibility
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

#endif //USE_OPTICK