mirror of
https://github.com/overte-org/overte.git
synced 2025-08-11 00:53:17 +02:00
Merge pull request #14709 from birarda/add-traits-to-dissectors
add message fragment handling to wireshark dissectors
This commit is contained in:
commit
73a5f30350
2 changed files with 187 additions and 21 deletions
|
@ -151,13 +151,16 @@ local packet_types = {
|
||||||
[96] = "OctreeDataFileReply",
|
[96] = "OctreeDataFileReply",
|
||||||
[97] = "OctreeDataPersist",
|
[97] = "OctreeDataPersist",
|
||||||
[98] = "EntityClone",
|
[98] = "EntityClone",
|
||||||
[99] = "EntityQueryInitialResultsComplete"
|
[99] = "EntityQueryInitialResultsComplete",
|
||||||
|
[100] = "BulkAvatarTraits"
|
||||||
}
|
}
|
||||||
|
|
||||||
local unsourced_packet_types = {
|
local unsourced_packet_types = {
|
||||||
["DomainList"] = true
|
["DomainList"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local fragments = {}
|
||||||
|
|
||||||
function p_hfudt.dissector(buf, pinfo, tree)
|
function p_hfudt.dissector(buf, pinfo, tree)
|
||||||
|
|
||||||
-- make sure this isn't a STUN packet - those don't follow HFUDT format
|
-- make sure this isn't a STUN packet - those don't follow HFUDT format
|
||||||
|
@ -235,6 +238,10 @@ function p_hfudt.dissector(buf, pinfo, tree)
|
||||||
|
|
||||||
local payload_offset = 4
|
local payload_offset = 4
|
||||||
|
|
||||||
|
local message_number = 0
|
||||||
|
local message_part_number = 0
|
||||||
|
local message_position = 0
|
||||||
|
|
||||||
-- if the message bit is set, handle the second word
|
-- if the message bit is set, handle the second word
|
||||||
if message_bit == 1 then
|
if message_bit == 1 then
|
||||||
payload_offset = 12
|
payload_offset = 12
|
||||||
|
@ -242,7 +249,7 @@ function p_hfudt.dissector(buf, pinfo, tree)
|
||||||
local second_word = buf(4, 4):le_uint()
|
local second_word = buf(4, 4):le_uint()
|
||||||
|
|
||||||
-- read message position from upper 2 bits
|
-- read message position from upper 2 bits
|
||||||
local message_position = bit32.rshift(second_word, 30)
|
message_position = bit32.rshift(second_word, 30)
|
||||||
local position = subtree:add(f_message_position, message_position)
|
local position = subtree:add(f_message_position, message_position)
|
||||||
|
|
||||||
if message_positions[message_position] ~= nil then
|
if message_positions[message_position] ~= nil then
|
||||||
|
@ -251,10 +258,12 @@ function p_hfudt.dissector(buf, pinfo, tree)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- read message number from lower 30 bits
|
-- read message number from lower 30 bits
|
||||||
subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF))
|
message_number = bit32.band(second_word, 0x3FFFFFFF)
|
||||||
|
subtree:add(f_message_number, message_number)
|
||||||
|
|
||||||
-- read the message part number
|
-- read the message part number
|
||||||
subtree:add(f_message_part_number, buf(8, 4):le_uint())
|
message_part_number = buf(8, 4):le_uint()
|
||||||
|
subtree:add(f_message_part_number, message_part_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
if obfuscation_bits ~= 0 then
|
if obfuscation_bits ~= 0 then
|
||||||
|
@ -288,25 +297,85 @@ function p_hfudt.dissector(buf, pinfo, tree)
|
||||||
i = i + 16
|
i = i + 16
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Domain packets
|
local payload_to_dissect = nil
|
||||||
if packet_type_text == "DomainList" then
|
|
||||||
Dissector.get("hf-domain"):call(buf(i):tvb(), pinfo, tree)
|
-- check if we have part of a message that we need to re-assemble
|
||||||
|
-- before it can be dissected
|
||||||
|
if obfuscation_bits == 0 then
|
||||||
|
if message_bit == 1 and message_position ~= 0 then
|
||||||
|
if fragments[message_number] == nil then
|
||||||
|
fragments[message_number] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
if fragments[message_number][message_part_number] == nil then
|
||||||
|
fragments[message_number][message_part_number] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set the properties for this fragment
|
||||||
|
fragments[message_number][message_part_number] = {
|
||||||
|
payload = buf(i):bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
-- if this is the last part, set our maximum part number
|
||||||
|
if message_position == 1 then
|
||||||
|
fragments[message_number].last_part_number = message_part_number
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if we have the last part
|
||||||
|
-- enumerate our parts for this message and see if everything is present
|
||||||
|
if fragments[message_number].last_part_number ~= nil then
|
||||||
|
local i = 0
|
||||||
|
local has_all = true
|
||||||
|
|
||||||
|
local finalMessage = ByteArray.new()
|
||||||
|
local message_complete = true
|
||||||
|
|
||||||
|
while i <= fragments[message_number].last_part_number do
|
||||||
|
if fragments[message_number][i] ~= nil then
|
||||||
|
finalMessage = finalMessage .. fragments[message_number][i].payload
|
||||||
|
else
|
||||||
|
-- missing this part, have to break until we have it
|
||||||
|
message_complete = false
|
||||||
|
end
|
||||||
|
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if message_complete then
|
||||||
|
debug("Message " .. message_number .. " is " .. finalMessage:len())
|
||||||
|
payload_to_dissect = ByteArray.tvb(finalMessage, message_number)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
payload_to_dissect = buf(i):tvb()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- AvatarData or BulkAvatarDataPacket
|
if payload_to_dissect ~= nil then
|
||||||
if packet_type_text == "AvatarData" or packet_type_text == "BulkAvatarData" then
|
-- Domain packets
|
||||||
Dissector.get("hf-avatar"):call(buf(i):tvb(), pinfo, tree)
|
if packet_type_text == "DomainList" then
|
||||||
|
Dissector.get("hf-domain"):call(payload_to_dissect, pinfo, tree)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- AvatarData or BulkAvatarDataPacket
|
||||||
|
if packet_type_text == "AvatarData" or
|
||||||
|
packet_type_text == "BulkAvatarData" or
|
||||||
|
packet_type_text == "BulkAvatarTraits" then
|
||||||
|
Dissector.get("hf-avatar"):call(payload_to_dissect, pinfo, tree)
|
||||||
|
end
|
||||||
|
|
||||||
|
if packet_type_text == "EntityEdit" then
|
||||||
|
Dissector.get("hf-entity"):call(payload_to_dissect, pinfo, tree)
|
||||||
|
end
|
||||||
|
|
||||||
|
if packet_types[packet_type] == "MicrophoneAudioNoEcho" or
|
||||||
|
packet_types[packet_type] == "MicrophoneAudioWithEcho" or
|
||||||
|
packet_types[packet_type] == "SilentAudioFrame" then
|
||||||
|
Dissector.get("hf-audio"):call(payload_to_dissect, pinfo, tree)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if packet_type_text == "EntityEdit" then
|
|
||||||
Dissector.get("hf-entity"):call(buf(i):tvb(), pinfo, tree)
|
|
||||||
end
|
|
||||||
|
|
||||||
if packet_types[packet_type] == "MicrophoneAudioNoEcho" or
|
|
||||||
packet_types[packet_type] == "MicrophoneAudioWithEcho" or
|
|
||||||
packet_types[packet_type] == "SilentAudioFrame" then
|
|
||||||
Dissector.get("hf-audio"):call(buf(i):tvb(), pinfo, tree)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return the size of the header
|
-- return the size of the header
|
||||||
|
|
|
@ -21,13 +21,31 @@ local f_avatar_data_default_rotations = ProtoField.string("hf_avatar.avatar_data
|
||||||
local f_avatar_data_default_translations = ProtoField.string("hf_avatar.avatar_data_default_translations", "Valid Default")
|
local f_avatar_data_default_translations = ProtoField.string("hf_avatar.avatar_data_default_translations", "Valid Default")
|
||||||
local f_avatar_data_sizes = ProtoField.string("hf_avatar.avatar_sizes", "Sizes")
|
local f_avatar_data_sizes = ProtoField.string("hf_avatar.avatar_sizes", "Sizes")
|
||||||
|
|
||||||
|
-- avatar trait data fields
|
||||||
|
local f_avatar_trait_data = ProtoField.bytes("hf_avatar.avatar_trait_data", "Avatar Trait Data")
|
||||||
|
|
||||||
|
local f_avatar_trait_id = ProtoField.guid("hf_avatar.trait_avatar_id", "Trait Avatar ID")
|
||||||
|
local f_avatar_trait_type = ProtoField.int8("hf_avatar.trait_type", "Trait Type")
|
||||||
|
local f_avatar_trait_version = ProtoField.int32("hf_avatar.trait_version", "Trait Version")
|
||||||
|
local f_avatar_trait_instance_id = ProtoField.guid("hf_avatar.trait_instance_id", "Trait Instance ID")
|
||||||
|
local f_avatar_trait_binary = ProtoField.bytes("hf_avatar.trait_binary", "Trait Binary Data")
|
||||||
|
|
||||||
p_hf_avatar.fields = {
|
p_hf_avatar.fields = {
|
||||||
f_avatar_id, f_avatar_data_parent_id
|
f_avatar_id, f_avatar_data_parent_id,
|
||||||
|
f_avatar_trait_data,
|
||||||
|
f_avatar_trait_type, f_avatar_trait_id,
|
||||||
|
f_avatar_trait_version, f_avatar_trait_binary,
|
||||||
|
f_avatar_trait_instance_id
|
||||||
}
|
}
|
||||||
|
|
||||||
local packet_type_extractor = Field.new('hfudt.type')
|
local packet_type_extractor = Field.new('hfudt.type')
|
||||||
|
|
||||||
|
INSTANCED_TYPES = {
|
||||||
|
[1] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
TOTAL_TRAIT_TYPES = 2
|
||||||
|
|
||||||
function p_hf_avatar.dissector(buf, pinfo, tree)
|
function p_hf_avatar.dissector(buf, pinfo, tree)
|
||||||
pinfo.cols.protocol = p_hf_avatar.name
|
pinfo.cols.protocol = p_hf_avatar.name
|
||||||
|
|
||||||
|
@ -52,7 +70,7 @@ function p_hf_avatar.dissector(buf, pinfo, tree)
|
||||||
|
|
||||||
add_avatar_data_subtrees(avatar_data)
|
add_avatar_data_subtrees(avatar_data)
|
||||||
|
|
||||||
else
|
elseif packet_type == 11 then
|
||||||
-- BulkAvatarData packet
|
-- BulkAvatarData packet
|
||||||
while i < buf:len() do
|
while i < buf:len() do
|
||||||
-- avatar_id is first 16 bytes
|
-- avatar_id is first 16 bytes
|
||||||
|
@ -65,9 +83,88 @@ function p_hf_avatar.dissector(buf, pinfo, tree)
|
||||||
|
|
||||||
add_avatar_data_subtrees(avatar_data)
|
add_avatar_data_subtrees(avatar_data)
|
||||||
end
|
end
|
||||||
|
elseif packet_type == 100 then
|
||||||
|
-- BulkAvatarTraits packet
|
||||||
|
|
||||||
|
-- loop over the packet until we're done reading it
|
||||||
|
while i < buf:len() do
|
||||||
|
i = i + read_avatar_trait_data(buf(i))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function read_avatar_trait_data(buf)
|
||||||
|
local i = 0
|
||||||
|
|
||||||
|
-- avatar_id is first 16 bytes
|
||||||
|
local avatar_id_bytes = buf(i, 16)
|
||||||
|
i = i + 16
|
||||||
|
|
||||||
|
local traits_map = {}
|
||||||
|
|
||||||
|
-- loop over all of the traits for this avatar
|
||||||
|
while i < buf:len() do
|
||||||
|
-- pull out this trait type
|
||||||
|
local trait_type = buf(i, 1):le_int()
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
debug("The trait type is " .. trait_type)
|
||||||
|
|
||||||
|
-- bail on our while if the trait type is null (-1)
|
||||||
|
if trait_type == -1 then break end
|
||||||
|
|
||||||
|
local trait_map = {}
|
||||||
|
|
||||||
|
-- pull out the trait version
|
||||||
|
trait_map.version = buf(i, 4):le_int()
|
||||||
|
i = i + 4
|
||||||
|
|
||||||
|
if INSTANCED_TYPES[trait_type] ~= nil then
|
||||||
|
-- pull out the trait instance ID
|
||||||
|
trait_map.instance_ID = buf(i, 16)
|
||||||
|
i = i + 16
|
||||||
|
end
|
||||||
|
|
||||||
|
-- pull out the trait binary size
|
||||||
|
trait_map.binary_size = buf(i, 2):le_int()
|
||||||
|
i = i + 2
|
||||||
|
|
||||||
|
-- unpack the binary data as long as this wasn't a delete
|
||||||
|
if trait_map.binary_size ~= -1 then
|
||||||
|
-- pull out the binary data for the trait
|
||||||
|
trait_map.binary_data = buf(i, trait_map.binary_size)
|
||||||
|
i = i + trait_map.binary_size
|
||||||
|
end
|
||||||
|
|
||||||
|
traits_map[trait_type] = trait_map
|
||||||
|
end
|
||||||
|
|
||||||
|
-- add a subtree including all of the data for this avatar
|
||||||
|
debug("Adding trait data of " .. i .. " bytes to the avatar tree")
|
||||||
|
local this_avatar_tree = avatar_subtree:add(f_avatar_trait_data, buf(0, i))
|
||||||
|
|
||||||
|
this_avatar_tree:add(f_avatar_trait_id, avatar_id_bytes)
|
||||||
|
|
||||||
|
-- enumerate the pulled traits and add them to the tree
|
||||||
|
local trait_type = 0
|
||||||
|
while trait_type < TOTAL_TRAIT_TYPES do
|
||||||
|
trait = traits_map[trait_type]
|
||||||
|
|
||||||
|
if trait ~= nil then
|
||||||
|
this_avatar_tree:add(f_avatar_trait_type, trait_type)
|
||||||
|
this_avatar_tree:add(f_avatar_trait_version, trait.version)
|
||||||
|
this_avatar_tree:add(f_avatar_trait_binary, trait.binary_data)
|
||||||
|
|
||||||
|
if trait.instance_ID ~= nil then
|
||||||
|
this_avatar_tree:add(f_avatar_trait_instance_id, trait.instance_ID)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
trait_type = trait_type + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
|
||||||
function add_avatar_data_subtrees(avatar_data)
|
function add_avatar_data_subtrees(avatar_data)
|
||||||
if avatar_data["has_flags"] then
|
if avatar_data["has_flags"] then
|
||||||
|
|
Loading…
Reference in a new issue