require "util" local p = Proto("pcmsg", "PictoChat Message") local MSG_TYPE = { USER_JOIN_A = 0, USER_JOIN_B = 1, IMAGE = 2, } local MSG_TYPE_MAP = { [MSG_TYPE.USER_JOIN_A] = "user join", [MSG_TYPE.USER_JOIN_B] = "user join", [MSG_TYPE.IMAGE] = "image", } p.fields.unknown = ProtoField.uint16("pcmsg.unknown", "Unknown") p.fields.padding = ProtoField.bytes("pcmsg.padding", "Padding") local dissect_msg_type = { } p.fields.user_addr = ProtoField.bytes("pcmsg.user.addr", "Address", base.COLON) p.fields.user_name = ProtoField.string("pcmsg.user.name", "Nickname") p.fields.user_msg = ProtoField.string("pcmsg.user.msg", "Message") p.fields.user_color = ProtoField.uint16("pcmsg.user.color", "Color", base.DEC, PROFILE_COLOR_MAP) p.fields.user_bday_month = ProtoField.uint8("pcmsg.user.bday_month", "Month") p.fields.user_bday_day = ProtoField.uint8("pcmsg.user.bday_day", "Day") dissect_msg_type[MSG_TYPE.USER_JOIN_A] = function (buffer, pinfo, tree) add_addr_le(tree, p.fields.user_addr, buffer(0x02, 6)) local user_name = buffer(0x08, 20):le_ustring() tree:add(p.fields.user_name, buffer(0x08, 20), user_name) tree:add(p.fields.user_msg, buffer(0x1c, 52), buffer(0x1c, 52):le_ustring()) tree:add_le(p.fields.user_color, buffer(0x50, 2)) local bday_str = string.format("Birthday: %02d/%02d", buffer(0x52, 1):uint(), buffer(0x53, 1):uint()) local bday = tree:add(buffer(0x52, 2), bday_str) bday:add(p.fields.user_bday_month, buffer(0x52, 1)) bday:add(p.fields.user_bday_day, buffer(0x53, 1)) register_addr_le(buffer(0x02, 6):raw(), user_name) pinfo.cols.info = string.format("%s user join (%s)", pinfo.cols.info, user_name) end dissect_msg_type[MSG_TYPE.USER_JOIN_B] = dissect_msg_type[MSG_TYPE.USER_JOIN_A] p.fields.img_addr = ProtoField.bytes("pcmsg.img.addr", "Address", base.COLON) p.fields.img_data = ProtoField.bytes("pcmsg.img.data", "Image data") dissect_msg_type[MSG_TYPE.IMAGE] = function (buffer, pinfo, tree) add_addr_le(tree, p.fields.img_addr, buffer(0x02, 6)) tree:add(p.fields.padding, buffer(0x08, 0x1c)) tree:add(p.fields.img_data, buffer(0x24)) local user = get_addr_label(fix_addr_endianness(buffer(0x02, 6):raw())) local rows = (buffer:len() - 0x24) / 0x800 pinfo.cols.info = string.format("%s %d row drawing by %s", pinfo.cols.info, rows, user) end dissect_msg_type[MSG_TYPE.USER_JOIN_B] = dissect_msg_type[MSG_TYPE.USER_JOIN_A] p.fields.type = ProtoField.uint8("pcmsg.type", "Type", base.DEC, MSG_TYPE_MAP) function p.dissector(buffer, pinfo, tree) local buffer_len = buffer:len() local mid = pc_global.pid_mid_map[pinfo.number] local type = buffer(0x01, 1):le_uint() local type_str = MSG_TYPE_MAP[type] or "" local subtree = tree:add(p, buffer(), string.format("%s %08x: %s, %d bytes", p.description, mid, type_str, buffer_len)) pinfo.cols.protocol = p.name pinfo.cols.info = string.format("[%08x]", mid) subtree:add_le(p.fields.unknown, buffer(0x00, 1)) subtree:add_le(p.fields.type, buffer(0x01, 1)) local subdissector = dissect_msg_type[type] if subdissector ~= nil then subdissector(buffer, pinfo, subtree) end return buffer_len end