Add --getProtocolVersionData and --getProtocolVersionHash arguments

This commit is contained in:
Dale Glass 2024-07-17 23:33:25 +02:00
parent afddb463ec
commit 13579a2b6b
3 changed files with 117 additions and 3 deletions

View file

@ -275,6 +275,14 @@ int main(int argc, const char* argv[]) {
"abortAfterInit",
"Debug option. Aborts after initialization, right before the program starts running the event loop."
);
QCommandLineOption getProtocolVersionHashOption(
"getProtocolVersionHash",
"Debug option. Returns the network protocol version MD5 hash."
);
QCommandLineOption getProtocolVersionDataOption(
"getProtocolVersionData",
"Debug option. Returns the network protocol detailed data in JSON."
);
// "--qmljsdebugger", which appears in output from "--help-all".
// Those below don't seem to be optional.
@ -321,6 +329,8 @@ int main(int argc, const char* argv[]) {
parser.addOption(abortAfterStartupOption);
parser.addOption(abortAfterInitOption);
parser.addOption(getPluginsOption);
parser.addOption(getProtocolVersionHashOption);
parser.addOption(getProtocolVersionDataOption);
QString applicationPath;
@ -455,6 +465,34 @@ int main(int argc, const char* argv[]) {
return 1;
}
}
if (parser.isSet(getProtocolVersionHashOption)) {
std::cout << protocolVersionsSignatureHex().toStdString() << std::endl;
return 0;
}
if (parser.isSet(getProtocolVersionDataOption)) {
auto protocolMap = protocolVersionsSignatureMap();
QMetaEnum packetMetaEnum = QMetaEnum::fromType<PacketTypeEnum::Value>();
QJsonArray packetTypesList;
auto keyList = protocolMap.keys();
std::sort(keyList.begin(), keyList.end()); // Sort by numeric value
for(const auto packet : keyList) {
QJsonObject data;
int intValue = static_cast<int>(packet);
QString keyName = packetMetaEnum.valueToKey(intValue);
data["name"] = keyName;
data["value"] = intValue;
data["version"] = versionForPacketType(packet);
packetTypesList.append(data);
}
std::cout << QJsonDocument(packetTypesList).toJson().toStdString() << std::endl;
return 0;
}
static const QString APPLICATION_CONFIG_FILENAME = "config.json";
QDir applicationDir(applicationPath);

View file

@ -130,6 +130,10 @@ void sendWrongProtocolVersionsSignature(bool sendWrongVersion) {
static QByteArray protocolVersionSignature;
static QString protocolVersionSignatureBase64;
static QString protocolVersionSignatureHex;
static QMap<PacketType, uint8_t> protocolVersionMap;
static void ensureProtocolVersionsSignature() {
static std::once_flag once;
std::call_once(once, [&] {
@ -139,12 +143,14 @@ static void ensureProtocolVersionsSignature() {
stream << numberOfProtocols;
for (uint8_t packetType = 0; packetType < numberOfProtocols; packetType++) {
uint8_t packetTypeVersion = static_cast<uint8_t>(versionForPacketType(static_cast<PacketType>(packetType)));
protocolVersionMap[static_cast<PacketType>(packetType)] = packetTypeVersion;
stream << packetTypeVersion;
}
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData(buffer);
protocolVersionSignature = hash.result();
protocolVersionSignatureBase64 = protocolVersionSignature.toBase64();
protocolVersionSignatureHex = protocolVersionSignature.toHex(0);
});
}
QByteArray protocolVersionsSignature() {
@ -161,3 +167,13 @@ QString protocolVersionsSignatureBase64() {
ensureProtocolVersionsSignature();
return protocolVersionSignatureBase64;
}
QString protocolVersionsSignatureHex() {
ensureProtocolVersionsSignature();
return protocolVersionSignatureHex;
}
QMap<PacketType, uint8_t> protocolVersionsSignatureMap() {
ensureProtocolVersionsSignature();
return protocolVersionMap;
}

View file

@ -31,8 +31,15 @@ class PacketTypeEnum {
Q_GADGET
Q_ENUMS(Value)
public:
// If adding a new packet packetType, you can replace one marked usable or add at the end.
// This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t
/**
* @brief Packet type identifier
*
* Identifies the type of packet being sent.
*
* @note If adding a new packet packetType, you can replace one marked usable or add at the end.
* @note This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t
*/
enum class Value : uint8_t {
Unknown,
DomainConnectRequestPending,
@ -143,6 +150,8 @@ public:
NUM_PACKET_TYPE
};
Q_ENUM(Value)
const static QHash<PacketTypeEnum::Value, PacketTypeEnum::Value> getReplicatedPacketMapping() {
const static QHash<PacketTypeEnum::Value, PacketTypeEnum::Value> REPLICATED_PACKET_MAPPING {
{ PacketTypeEnum::Value::MicrophoneAudioNoEcho, PacketTypeEnum::Value::ReplicatedMicrophoneAudioNoEcho },
@ -219,10 +228,60 @@ const int NUM_BYTES_MD5_HASH = 16;
// NOTE: There is a max limit of 255, hopefully we have a better way to manage this by then.
typedef uint8_t PacketVersion;
/**
* @brief Returns the version number of the given packet type
*
* If the implementation of a packet type is modified in an incompatible way, the implementation
* of this function needs to be modified to return an incremented value.
*
* This is used to determine whether the protocol is compatible between client and server.
*
* @note Version is limited to a max of 255.
*
* @param packetType Type of packet
* @return PacketVersion Version
*/
PacketVersion versionForPacketType(PacketType packetType);
QByteArray protocolVersionsSignature(); /// returns a unique signature for all the current protocols
/**
* @brief Returns a unique signature for all the current protocols
*
* This computes a MD5 hash that expresses the state of the protocol's specification. The calculation
* is done in ensureProtocolVersionsSignature and accounts for the following:
*
* * Number of known packet types
* * versionForPacketType(type) for each packet type.
*
* There's no provision for backwards compatibility, anything that changes this calculation is a protocol break.
*
* @return QByteArray MD5 digest as a byte array
*/
QByteArray protocolVersionsSignature();
/***
* @brief Returns a unique signature for all the current protocols
*
* Same as protocolVersionsSignature(), in base64.
*/
QString protocolVersionsSignatureBase64();
/***
* @brief Returns a unique signature for all the current protocols
*
* Same as protocolVersionsSignature(), in hex;
*/
QString protocolVersionsSignatureHex();
/***
* @brief Returns the data used to compute the protocol version
*
* The key is the packet type. The value is the version for that packet type.
*
* Used for aiding in development.
*/
QMap<PacketType, uint8_t> protocolVersionsSignatureMap();
#if (PR_BUILD || DEV_BUILD)
void sendWrongProtocolVersionsSignature(bool sendWrongVersion); /// for debugging version negotiation
#endif
@ -428,4 +487,5 @@ enum class AvatarQueryVersion : PacketVersion {
ConicalFrustums = 22
};
#endif // hifi_PacketHeaders_h