This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

wireshark lua dissector – efficient way to do a binary block write to a file?

0

I am writing a lua dissector for a propietary protocol. The packets include bytes of embedded .png images that are contained in a tvb (buffer) object that I need to write to a .png file. In order to successfully write them to a file, below are couple of ways attempted. Both required "walking through" each byte of the buffer with string.char, making them VERY SLOW performing. Is there a better way to do this in lua, maybe with a fwrite-like single call to write the entire range of buffer bytes?

-- Attempt #1
-- ============

local filename = "foo.png"

local file = assert(io.open(filename, "w+b"))

local i = 0

local lopt = size

local value

while lopt > 0 do

value = buffer(offset+5+i,1):uint()

    file:write(string.char(value))

    i = i + 1

    lopt = lopt - 1

end

file:write(buffer(offset+5):string())

file:flush()

file:close()

– Attempt #2 – ============ local filename = "foo.png"

local file = assert(fopen(filename, "w+b"))

local t = {}

for i=0,size

do t[i] = string.char(buffer(offset+4+i,1):uint())

end

file:write(unpack(t))

file:flush()

file:close()

asked 04 Aug ‘15, 19:02

mfbaker's gravatar image

mfbaker
16448
accept rate: 0%

edited 04 Aug ‘15, 19:12

Hadriel's gravatar image

Hadriel
2.7k2939


One Answer:

1

Yes: in Wireshark/tshark version 1.12 the Tvb, TvbRange, and ByteArray objects were given new methods called "raw()", which gives back a Lua string of the contents of the Tvb/TvbRange/ByteArray. The functions are documented in the API, and noted in the changes to the API wiki page. (they actually got added in 1.11, but that was a development release, so for general release it's 1.12)

So if you know the beginning offset in the Tvb and the length, you can just grab the whole chunk at once and then write it to the file in one chunk. In your example above, I assume that "buffer" is the Tvb, "size" is the size of the PNG chunk, and "offset+5" is where it begins, in which case this would do it:

file:write(buffer:raw(offset+5, size))

(plus the other stuff to open/close the file, which is presumably being done outside your dissector function anyway)

answered 04 Aug '15, 19:27

Hadriel's gravatar image

Hadriel
2.7k2939
accept rate: 18%

Thank you so much, Hadriel -- using the "raw()" API worked, with ~4x performance improvement! A capture file that I was testing had 5300 images, which before the change took about 23 seconds to load. With using raw() API instead, the same file took 5.9 seconds -- an awesome improvement!

(05 Aug '15, 09:40) mfbaker

If an answer has solved your issue, please accept the answer for the benefit of other users by clicking the checkmark icon next to the answer. Please read the FAQ for more information.

(05 Aug '15, 11:06) grahamb ♦

Question is answered, thanks again, Hadriel!

(05 Aug '15, 14:38) mfbaker