First pass idLib conversion from hex rays4.
This commit is contained in:
@@ -0,0 +1,494 @@
|
||||
#pragma once
|
||||
|
||||
// Recovered AMQP 0-8 surface used by tungsten's telemetry clients. The wire
|
||||
// protocol remains AMQP compatible; only the old Xbox socket/thread plumbing
|
||||
// is replaced by the portable idTCP and Win32 primitives already in idLib.
|
||||
#include "idlib/precompiled.h"
|
||||
#include "idlib/sys/sys_networking.h"
|
||||
|
||||
#ifdef nullptr
|
||||
#undef nullptr
|
||||
#endif
|
||||
#ifdef _stricmp
|
||||
#undef _stricmp
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
template<class T>
|
||||
class idMQList {
|
||||
public:
|
||||
explicit idMQList(int initialGranularity = 16)
|
||||
: list(nullptr), num(0), size(0),
|
||||
granularity(static_cast<short>(initialGranularity)), memTag(5),
|
||||
listStatic(0) {}
|
||||
idMQList(const idMQList& other) : idMQList(other.granularity) {
|
||||
*this = other;
|
||||
}
|
||||
~idMQList() { delete[] list; }
|
||||
idMQList& operator=(const idMQList& other) {
|
||||
if (this == &other) return *this;
|
||||
SetNum(other.num);
|
||||
for (int index = 0; index < num; ++index) list[index] = other[index];
|
||||
return *this;
|
||||
}
|
||||
void Clear() { num = 0; }
|
||||
int Num() const { return num; }
|
||||
T* Ptr() { return list; }
|
||||
const T* Ptr() const { return list; }
|
||||
T& operator[](int index) { return list[index]; }
|
||||
const T& operator[](int index) const { return list[index]; }
|
||||
void SetNum(int newNum) {
|
||||
if (newNum > size) Resize(newNum);
|
||||
if (newNum >= 0 && newNum <= size) num = newNum;
|
||||
}
|
||||
int Append(const T& value) {
|
||||
if (num == size && !Resize(num + 1)) return -1;
|
||||
list[num] = value;
|
||||
return num++;
|
||||
}
|
||||
bool RemoveIndex(int index) {
|
||||
if (index < 0 || index >= num) return false;
|
||||
for (int i = index; i + 1 < num; ++i) list[i] = list[i + 1];
|
||||
--num;
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
bool Resize(int required) {
|
||||
const int step = granularity > 0 ? granularity : 16;
|
||||
const int newSize = ((required + step - 1) / step) * step;
|
||||
T* replacement = new (std::nothrow) T[newSize];
|
||||
if (replacement == nullptr) return false;
|
||||
for (int index = 0; index < num; ++index) replacement[index] = list[index];
|
||||
delete[] list;
|
||||
list = replacement;
|
||||
size = newSize;
|
||||
return true;
|
||||
}
|
||||
T* list;
|
||||
int num;
|
||||
int size;
|
||||
short granularity;
|
||||
unsigned char memTag;
|
||||
unsigned char listStatic;
|
||||
};
|
||||
|
||||
class idMQKeyValue {
|
||||
public:
|
||||
idMQKeyValue() : key(), value() {}
|
||||
idMQKeyValue(const char* keyText, const char* valueText)
|
||||
: key(keyText), value(valueText) {}
|
||||
const idStr& GetKey() const { return key; }
|
||||
const idStr& GetValue() const { return value; }
|
||||
idStr key;
|
||||
idStr value;
|
||||
};
|
||||
|
||||
class idMQTable {
|
||||
public:
|
||||
idMQTable() : args(), hash{} {}
|
||||
void Clear() { args.Clear(); }
|
||||
int GetNumKeyVals() const { return args.Num(); }
|
||||
const idMQKeyValue* GetKeyVal(int index) const {
|
||||
return index >= 0 && index < args.Num() ? &args[index] : nullptr;
|
||||
}
|
||||
void Set(const char* key, const char* value) {
|
||||
const char* safeKey = key == nullptr ? "" : key;
|
||||
for (int index = 0; index < args.Num(); ++index) {
|
||||
if (_stricmp(args[index].key.c_str(), safeKey) == 0) {
|
||||
args[index].value = value == nullptr ? "" : value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
args.Append(idMQKeyValue(safeKey, value == nullptr ? "" : value));
|
||||
}
|
||||
const char* GetString(const char* key, const char* defaultValue = "") const {
|
||||
const char* safeKey = key == nullptr ? "" : key;
|
||||
for (int index = 0; index < args.Num(); ++index) {
|
||||
if (_stricmp(args[index].key.c_str(), safeKey) == 0) {
|
||||
return args[index].value.c_str();
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
private:
|
||||
idMQList<idMQKeyValue> args;
|
||||
std::uint32_t hash[8];
|
||||
};
|
||||
|
||||
enum MQErrors_t {
|
||||
MQERROR_NONE = 0,
|
||||
MQERROR_UNKNOWN,
|
||||
MQERROR_INVALID_FRAME,
|
||||
MQERROR_FRAME_OVERFLOW,
|
||||
MQERROR_SESSION_NOT_FOUND,
|
||||
MQERROR_STREAM_ERROR,
|
||||
MQERROR_CONNECTION_START,
|
||||
MQERROR_BAD_SPEC_VERSION,
|
||||
MQERROR_AUTH_FAILED,
|
||||
MQERROR_UNEXPECTED_CLASS,
|
||||
MQERROR_UNEXPECTED_METHOD,
|
||||
MQERROR_SERVER_CLOSED
|
||||
};
|
||||
|
||||
enum MQAssemblerState_t {
|
||||
MQ_CMDSTATE_NEED_METHOD = 0,
|
||||
MQ_CMDSTATE_NEED_HEADER,
|
||||
MQ_CMDSTATE_NEED_BODY,
|
||||
MQ_CMDSTATE_COMPLETE
|
||||
};
|
||||
|
||||
enum amqpClassId_t {
|
||||
AMQP_CLASS_CONNECTION = 10,
|
||||
AMQP_CLASS_CHANNEL = 20,
|
||||
AMQP_CLASS_ACCESS = 30,
|
||||
AMQP_CLASS_EXCHANGE = 40,
|
||||
AMQP_CLASS_QUEUE = 50,
|
||||
AMQP_CLASS_BASIC = 60
|
||||
};
|
||||
|
||||
enum amqpFrameType_t {
|
||||
AMQP_FRAME_METHOD = 1,
|
||||
AMQP_FRAME_HEADER = 2,
|
||||
AMQP_FRAME_BODY = 3,
|
||||
AMQP_FRAME_HEARTBEAT = 8,
|
||||
AMQP_FRAME_END = 0xCE
|
||||
};
|
||||
|
||||
struct amqpEndpoint_t {
|
||||
amqpEndpoint_t();
|
||||
|
||||
idStr host;
|
||||
unsigned short port;
|
||||
idStr username;
|
||||
idStr password;
|
||||
idStr vhost;
|
||||
unsigned short channelMax;
|
||||
unsigned short frameMax;
|
||||
unsigned short heartbeat;
|
||||
bool nonBlocking;
|
||||
bool silent;
|
||||
int minorVersion;
|
||||
int majorVersion;
|
||||
};
|
||||
|
||||
struct amqpShutdownReason_t {
|
||||
amqpShutdownReason_t()
|
||||
: replyCode(0), cId(0), mId(0), error(MQERROR_NONE), replyText("") {}
|
||||
unsigned short replyCode;
|
||||
unsigned short cId;
|
||||
unsigned short mId;
|
||||
MQErrors_t error;
|
||||
const char* replyText;
|
||||
};
|
||||
|
||||
class idMQFrame;
|
||||
|
||||
class idMQMethod {
|
||||
public:
|
||||
virtual ~idMQMethod() = default;
|
||||
virtual int GetClassId() const = 0;
|
||||
virtual int GetMethodId() const = 0;
|
||||
virtual bool HasContent() const { return false; }
|
||||
virtual bool IsAsync() const { return false; }
|
||||
virtual void Populate(idMQFrame& frame) = 0;
|
||||
virtual void ToFrame(idMQFrame& frame) = 0;
|
||||
};
|
||||
|
||||
class idMQFrame {
|
||||
public:
|
||||
idMQFrame();
|
||||
idMQFrame(unsigned char frameType, unsigned short channelNumber);
|
||||
|
||||
void Clear();
|
||||
void ReadData(void* destination, int length);
|
||||
void WriteData(const void* source, int length);
|
||||
unsigned char ReadByte();
|
||||
unsigned short ReadUInt16();
|
||||
unsigned int ReadUInt32();
|
||||
std::uint64_t ReadUInt64();
|
||||
bool ReadBool();
|
||||
idStr ReadShortString();
|
||||
void ReadString(idMQList<unsigned char>& value);
|
||||
void ReadTable(idMQTable& value);
|
||||
bool ReadPropertyPresence();
|
||||
void FinalizeReadPresence();
|
||||
|
||||
void WriteByte(unsigned char value);
|
||||
void WriteUInt16(unsigned short value);
|
||||
void WriteUInt32(unsigned int value);
|
||||
void WriteUInt64(std::uint64_t value);
|
||||
void WriteBool(bool value);
|
||||
void WriteShortString(const idStr& value);
|
||||
void WriteString(const idMQList<unsigned char>& value);
|
||||
void WriteTable(const idMQTable& value);
|
||||
void WritePropertyPresence(bool present);
|
||||
void FinalizeWritePresence();
|
||||
void FlushWriteBitBuffer();
|
||||
void FinalizeFrame();
|
||||
|
||||
int ReadFromStream(class idMQTCP& stream);
|
||||
int WriteToStream(class idMQTCP& stream);
|
||||
|
||||
unsigned char type;
|
||||
unsigned short channel;
|
||||
idMQList<unsigned char> data;
|
||||
int readPos;
|
||||
bool locked;
|
||||
bool resetReadBitBuffer;
|
||||
unsigned char readBitBuffer;
|
||||
unsigned int readBitMask;
|
||||
bool flushWriteBitBuffer;
|
||||
unsigned char writeBitBuffer;
|
||||
unsigned int writeBitMask;
|
||||
unsigned short readPresenceBuffer;
|
||||
unsigned short readPresencePosition;
|
||||
unsigned short writePresenceBuffer;
|
||||
unsigned short writePresencePosition;
|
||||
};
|
||||
|
||||
class idMQTCP {
|
||||
public:
|
||||
idMQTCP();
|
||||
~idMQTCP();
|
||||
bool Connect(const char* host, unsigned short port, bool nonBlocking,
|
||||
bool silent);
|
||||
void Close();
|
||||
bool IsOpen() const;
|
||||
int Read(void* data, int size, bool blocking = true,
|
||||
int timeoutMS = 5000);
|
||||
int Write(const void* data, int size, bool blocking = true,
|
||||
int timeoutMS = 5000);
|
||||
int ReadByte(unsigned char& value, bool blocking = true,
|
||||
int timeoutMS = 5000);
|
||||
int ReadUInt16(unsigned short& value, bool blocking = true,
|
||||
int timeoutMS = 5000);
|
||||
int ReadUInt32(unsigned int& value, bool blocking = true,
|
||||
int timeoutMS = 5000);
|
||||
|
||||
idTCP tcp;
|
||||
};
|
||||
|
||||
class idMQContentHeader {
|
||||
public:
|
||||
idMQContentHeader() : bodyLength(0) {}
|
||||
virtual ~idMQContentHeader() = default;
|
||||
virtual int GetProtocolId() const = 0;
|
||||
virtual void Populate(idMQFrame& frame) = 0;
|
||||
virtual void ToFrame(idMQFrame& frame) = 0;
|
||||
|
||||
std::uint64_t bodyLength;
|
||||
};
|
||||
|
||||
class idMQBuffer {
|
||||
public:
|
||||
idMQBuffer();
|
||||
void Clear();
|
||||
void WriteData(const void* data, int size);
|
||||
void WriteUInt16(unsigned short value, bool bigEndian = true);
|
||||
void WriteUInt32(unsigned int value, bool bigEndian = true);
|
||||
|
||||
idMQList<unsigned char> body;
|
||||
int readPos;
|
||||
};
|
||||
|
||||
class idMQFrameHandler {
|
||||
public:
|
||||
explicit idMQFrameHandler(const amqpEndpoint_t& endpointValue);
|
||||
~idMQFrameHandler();
|
||||
bool Connect();
|
||||
void Close();
|
||||
int SendFrame(idMQFrame& frame);
|
||||
int ReadFrame(idMQFrame& frame);
|
||||
bool SendHeader();
|
||||
|
||||
amqpEndpoint_t endpoint;
|
||||
idSysMutex readLock;
|
||||
idSysMutex writeLock;
|
||||
idMQTCP tcp;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class idDeferredResult {
|
||||
public:
|
||||
idDeferredResult() : value(), filled(false), signal(false) {}
|
||||
|
||||
void SetValue(const T& newValue) {
|
||||
value = newValue;
|
||||
filled = true;
|
||||
signal.Raise();
|
||||
}
|
||||
bool GetValue(T& result) {
|
||||
if (!signal.Wait(5000) || !filled) return false;
|
||||
result = value;
|
||||
filled = false;
|
||||
return true;
|
||||
}
|
||||
bool GetValue() {
|
||||
if (!signal.Wait(5000) || !filled) return false;
|
||||
filled = false;
|
||||
return true;
|
||||
}
|
||||
void Clear() {
|
||||
filled = false;
|
||||
signal.Clear();
|
||||
}
|
||||
|
||||
T value;
|
||||
bool filled;
|
||||
idSysSignal signal;
|
||||
};
|
||||
|
||||
class idMQCommand {
|
||||
public:
|
||||
idMQCommand();
|
||||
~idMQCommand();
|
||||
void Reset();
|
||||
|
||||
idMQMethod* method;
|
||||
idMQContentHeader* contentHeader;
|
||||
bool complete;
|
||||
idMQList<unsigned char> contentBody;
|
||||
std::uint64_t remainingBodyBytes;
|
||||
};
|
||||
|
||||
class idMQCommandBuilder {
|
||||
public:
|
||||
idMQCommandBuilder();
|
||||
MQErrors_t HandleFrame(idMQCommand& command, idMQFrame& frame);
|
||||
|
||||
MQAssemblerState_t state;
|
||||
std::uint64_t remainingBytes;
|
||||
};
|
||||
|
||||
class idMQChannel;
|
||||
class idMQSessionManager;
|
||||
|
||||
class idMQConnection {
|
||||
public:
|
||||
idMQConnection();
|
||||
~idMQConnection();
|
||||
void Init(amqpEndpoint_t& endpoint);
|
||||
bool Connect();
|
||||
void Close();
|
||||
void Close(const char* reason, MQErrors_t error);
|
||||
void Close(amqpShutdownReason_t& reason);
|
||||
void SendFrame(idMQFrame& frame);
|
||||
idMQChannel* GetChannel();
|
||||
|
||||
unsigned int frameMaxSize;
|
||||
idMQList<idStr> knownHosts;
|
||||
idMQFrameHandler* framer;
|
||||
idMQSessionManager* sessionManager;
|
||||
class idMQSession* sessionZero;
|
||||
volatile bool terminateConnection;
|
||||
volatile bool connectionTerminated;
|
||||
volatile bool isClosing;
|
||||
unsigned int threadHandle;
|
||||
amqpShutdownReason_t shutdownReason;
|
||||
|
||||
private:
|
||||
bool OpenCommunications();
|
||||
void CreateThread();
|
||||
void MessageThread();
|
||||
static unsigned int StaticThread(void* connection);
|
||||
};
|
||||
|
||||
class idMQSession {
|
||||
public:
|
||||
idMQSession(int channelNumber, idMQConnection* connection);
|
||||
~idMQSession();
|
||||
void Init(bool connectionChannel = false);
|
||||
void Close();
|
||||
void Close(const char* reason, MQErrors_t error,
|
||||
bool notifyServer = true);
|
||||
void HandleFrame(idMQFrame& frame);
|
||||
void SendCommand(idMQCommand& command);
|
||||
|
||||
idMQConnection* connection;
|
||||
idMQCommandBuilder cmdBuilder;
|
||||
idMQChannel* protocol;
|
||||
idMQCommand currentCommand;
|
||||
int channelNumber;
|
||||
bool isOpen;
|
||||
};
|
||||
|
||||
class idMQSessionManager {
|
||||
public:
|
||||
explicit idMQSessionManager(idMQConnection* connection);
|
||||
~idMQSessionManager();
|
||||
void Init(int maximumSessions);
|
||||
void Shutdown();
|
||||
idMQSession* CreateSession();
|
||||
idMQSession* Lookup(int channelNumber);
|
||||
|
||||
bool initialized;
|
||||
idMQConnection* connection;
|
||||
int maxSessions;
|
||||
idMQList<idMQSession*> sessionList;
|
||||
};
|
||||
|
||||
class idMQClientThread {
|
||||
public:
|
||||
idMQClientThread();
|
||||
virtual ~idMQClientThread();
|
||||
virtual void StartMessageSystem() { StartThread("AMQP Client"); }
|
||||
virtual void StopMessageSystem() { StopThread(true); }
|
||||
virtual void PreRun() {}
|
||||
virtual void ThreadSlice() { Sys_Yield(); }
|
||||
virtual void OnThreadTerminate() {}
|
||||
|
||||
void StartThread(const char* threadName);
|
||||
void StopThread(bool waitForStop);
|
||||
|
||||
unsigned int handle;
|
||||
volatile bool signalQuit;
|
||||
volatile bool terminated;
|
||||
idMQConnection connection;
|
||||
int retryTime;
|
||||
|
||||
protected:
|
||||
static void Connect(idMQClientThread* thread);
|
||||
static unsigned int Thread(void* thread);
|
||||
};
|
||||
|
||||
class idMQClient : public idMQClientThread {};
|
||||
|
||||
class idMQGraphiteClient : public idMQClientThread {
|
||||
public:
|
||||
struct graphiteEvent_t {
|
||||
const char* eventName;
|
||||
int count;
|
||||
float duration;
|
||||
float mean;
|
||||
float mean2;
|
||||
};
|
||||
|
||||
idMQGraphiteClient(const idStr& exchangeName, const idStr& metricPrefix);
|
||||
~idMQGraphiteClient() override;
|
||||
void StartMessageSystem() override;
|
||||
void PreRun() override;
|
||||
void ThreadSlice() override;
|
||||
void OnThreadTerminate() override;
|
||||
void LogEvent(const idStr& eventName, float duration);
|
||||
|
||||
int reportTime;
|
||||
idMQChannel* channel;
|
||||
idMQList<graphiteEvent_t> outgoingEvents;
|
||||
idStr exchange;
|
||||
idStr prefix;
|
||||
idSysMutex threadMutex;
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idMQTCP) == 20, "Recovered idMQTCP ABI changed");
|
||||
static_assert(sizeof(idMQList<unsigned char>) == 16,
|
||||
"Recovered AMQP list ABI changed");
|
||||
static_assert(sizeof(idMQTable) == 48, "Recovered AMQP table ABI changed");
|
||||
static_assert(sizeof(idMQBuffer) == 20, "Recovered idMQBuffer ABI changed");
|
||||
static_assert(sizeof(idMQMethod) == 4, "Recovered idMQMethod ABI changed");
|
||||
static_assert(sizeof(idMQContentHeader) == 16,
|
||||
"Recovered idMQContentHeader ABI changed");
|
||||
#endif
|
||||
Reference in New Issue
Block a user