feat: calculate ddnet uuids based on name

This commit is contained in:
ChillerDragon 2024-04-19 10:02:45 +08:00
parent 651efbe95a
commit 4c434752dc
2 changed files with 73 additions and 9 deletions

View file

@ -1,13 +1,52 @@
from twnet_parser.uuid_manager import UuuidMangager
from twnet_parser.uuid_manager import UuidManager
def test_register_name_should_not_crash() -> None:
manager = UuuidMangager()
manager = UuidManager()
manager.register_name(0, 'foo')
def test_register_name_get_name() -> None:
manager = UuuidMangager()
manager = UuidManager()
manager.register_name(0, 'foo')
uuid = manager.get_uuid_by_type(0)
assert uuid.name == 'foo'
def test_calculate_uuid() -> None:
manager = UuidManager()
cap = manager.calculate_uuid('capabilities@ddnet.tw')
# verified with the ddnet uuid tool and by looking at the network traffic
# f621a5a1-f585-3775-8e73-41beee79f2b2
assert cap == b'\xf6\x21\xa5\xa1\xf5\x85\x37\x75\x8e\x73\x41\xbe\xee\x79\xf2\xb2'
def test_register_calc_uuid() -> None:
manager = UuidManager()
manager.register_name(0, 'foo')
uuid = manager.get_uuid_by_type(0)
# 09ea064a-7bb3-3557-bf2f-7ae3db95106a
assert uuid.name == 'foo'
assert uuid.uuid == b'\x09\xea\x06\x4a\x7b\xb3\x35\x57\xbf\x2f\x7a\xe3\xdb\x95\x10\x6a'
def test_register_calc_multiple_uuids() -> None:
manager = UuidManager()
manager.register_name(0, 'foo')
manager.register_name(1, 'bar')
foo = manager.get_uuid_by_type(0)
bar = manager.get_uuid_by_type(1)
# 09ea064a-7bb3-3557-bf2f-7ae3db95106a
assert foo.type_id == 0
assert foo.name == 'foo'
assert foo.uuid == b'\x09\xea\x06\x4a\x7b\xb3\x35\x57\xbf\x2f\x7a\xe3\xdb\x95\x10\x6a'
# 71111349-4e74-3e36-81ff-fe712097b4cc
assert bar.type_id == 1
assert bar.name == 'bar'
assert bar.uuid == b'\x71\x11\x13\x49\x4e\x74\x3e\x36\x81\xff\xfe\x71\x20\x97\xb4\xcc'
def test_register_conflicting_types() -> None:
# TODO: this should crash
manager = UuidManager()
manager.register_name(0, 'foo')
manager.register_name(0, 'bar')

View file

@ -1,24 +1,32 @@
import hashlib
UUID_MAXSTRSIZE = 37
"""
12345678-0123-5678-0123-567890123456
"""
UUID_MAXSTRSIZE = 37
UUID_INVALID = -2
UUID_UNKNOWN = -1
OFFSET_UUID = 1 << 16
"""
OFFSET_UUID (65536)
"""
OFFSET_UUID = 1 << 16
TEEWORLDS_NAMESPACE = b'\xe0\x5d\xda\xaa\xc4\xe6\x4c\xfb\xb6\x42\x5d\x48\xe8\x0c\x00\x29'
"""
e05ddaaa-c4e6-4cfb-b642-5d48e80c0029
"""
class DDNetUuid:
def __init__(self, type_id: int, name: str) -> None:
def __init__(self, type_id: int, name: str, uuid: bytes) -> None:
self.name = name
self.type_id = type_id
self.uuid = uuid
class UuuidMangager:
class UuidManager:
def __init__(self) -> None:
self.uuids: list[DDNetUuid] = []
@ -36,8 +44,25 @@ class UuuidMangager:
What is sent over the network can also be a type_index which is
the type_id minus the OFFSET_UUID
"""
self.uuids.append(DDNetUuid(type_id, name))
self.uuids.append(DDNetUuid(type_id, name, self.calculate_uuid(name)))
def get_uuid_by_type(self, type_id: int) -> DDNetUuid:
return self.uuids[type_id]
def calculate_uuid(self, name: str) -> bytes:
md5_hash = hashlib.md5()
md5_hash.update(TEEWORLDS_NAMESPACE)
md5_hash.update(name.encode('utf-8'))
digest = bytearray(md5_hash.digest())
# set version 3 (UUID is generated by MD5 hashing a namespace identifier and a name)
digest[6] &= 0x0f
digest[6] |= 0x30
# set variant 1 (RFC 4122)
digest[8] &= 0x3f
digest[8] |= 0x80
return bytes(digest)