#include "uuid_manager.h" #include #include #include static const CUuid TEEWORLDS_NAMESPACE = {{// "e05ddaaa-c4e6-4cfb-b642-5d48e80c0029" 0xe0, 0x5d, 0xda, 0xaa, 0xc4, 0xe6, 0x4c, 0xfb, 0xb6, 0x42, 0x5d, 0x48, 0xe8, 0x0c, 0x00, 0x29}}; CUuid RandomUuid() { CUuid Result; secure_random_fill(&Result, sizeof(Result)); Result.m_aData[6] &= 0x0f; Result.m_aData[6] |= 0x40; Result.m_aData[8] &= 0x3f; Result.m_aData[8] |= 0x80; return Result; } CUuid CalculateUuid(const char *pName) { MD5_CTX Md5; md5_init(&Md5); md5_update(&Md5, TEEWORLDS_NAMESPACE.m_aData, sizeof(TEEWORLDS_NAMESPACE.m_aData)); // Without terminating NUL. md5_update(&Md5, (const unsigned char *)pName, str_length(pName)); MD5_DIGEST Digest = md5_finish(&Md5); CUuid Result; for(unsigned i = 0; i < sizeof(Result.m_aData); i++) { Result.m_aData[i] = Digest.data[i]; } Result.m_aData[6] &= 0x0f; Result.m_aData[6] |= 0x30; Result.m_aData[8] &= 0x3f; Result.m_aData[8] |= 0x80; return Result; } void FormatUuid(CUuid Uuid, char *pBuffer, unsigned BufferLength) { unsigned char *p = Uuid.m_aData; str_format(pBuffer, BufferLength, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); } int ParseUuid(CUuid *pUuid, const char *pBuffer) { if(str_length(pBuffer) + 1 != UUID_MAXSTRSIZE) { return 2; } char aCopy[UUID_MAXSTRSIZE]; str_copy(aCopy, pBuffer, sizeof(aCopy)); // 01234567-9012-4567-9012-456789012345 if(aCopy[8] != '-' || aCopy[13] != '-' || aCopy[18] != '-' || aCopy[23] != '-') { return 1; } aCopy[8] = aCopy[13] = aCopy[18] = aCopy[23] = 0; if(0 || str_hex_decode(pUuid->m_aData + 0, 4, aCopy + 0) || str_hex_decode(pUuid->m_aData + 4, 2, aCopy + 9) || str_hex_decode(pUuid->m_aData + 6, 2, aCopy + 14) || str_hex_decode(pUuid->m_aData + 8, 2, aCopy + 19) || str_hex_decode(pUuid->m_aData + 10, 6, aCopy + 24)) { return 1; } return 0; } bool CUuid::operator==(const CUuid &Other) const { return mem_comp(this, &Other, sizeof(*this)) == 0; } bool CUuid::operator!=(const CUuid &Other) const { return !(*this == Other); } static int GetIndex(int ID) { return ID - OFFSET_UUID; } static int GetID(int Index) { return Index + OFFSET_UUID; } void CUuidManager::RegisterName(int ID, const char *pName) { dbg_assert(GetIndex(ID) == m_aNames.size(), "names must be registered with increasing ID"); CName Name; Name.m_pName = pName; Name.m_Uuid = CalculateUuid(pName); dbg_assert(LookupUuid(Name.m_Uuid) == -1, "duplicate uuid"); m_aNames.add(Name); CNameIndexed NameIndexed; NameIndexed.m_Uuid = Name.m_Uuid; NameIndexed.m_ID = GetIndex(ID); m_aNamesSorted.add(NameIndexed); } CUuid CUuidManager::GetUuid(int ID) const { return m_aNames[GetIndex(ID)].m_Uuid; } const char *CUuidManager::GetName(int ID) const { return m_aNames[GetIndex(ID)].m_pName; } int CUuidManager::LookupUuid(CUuid Uuid) const { sorted_array::range Pos = ::find_binary(m_aNamesSorted.all(), Uuid); if(!Pos.empty()) { return GetID(Pos.front().m_ID); } return UUID_UNKNOWN; } int CUuidManager::NumUuids() const { return m_aNames.size(); } int CUuidManager::UnpackUuid(CUnpacker *pUnpacker) const { CUuid Temp; return UnpackUuid(pUnpacker, &Temp); } int CUuidManager::UnpackUuid(CUnpacker *pUnpacker, CUuid *pOut) const { const CUuid *pUuid = (const CUuid *)pUnpacker->GetRaw(sizeof(*pUuid)); if(pUuid == NULL) { return UUID_INVALID; } *pOut = *pUuid; return LookupUuid(*pUuid); } void CUuidManager::PackUuid(int ID, CPacker *pPacker) const { CUuid Uuid = GetUuid(ID); pPacker->AddRaw(&Uuid, sizeof(Uuid)); } void CUuidManager::DebugDump() const { for(int i = 0; i < m_aNames.size(); i++) { char aBuf[UUID_MAXSTRSIZE]; FormatUuid(m_aNames[i].m_Uuid, aBuf, sizeof(aBuf)); dbg_msg("uuid", "%s %s", aBuf, m_aNames[i].m_pName); } }