Skip to content

Commit 909832e

Browse files
committed
1) VARLEN fields can now be anywhere in a message (not just at the end of it). 2) Fields with the same name but different length are now allowed.
1 parent b5c880e commit 909832e

File tree

1 file changed

+67
-34
lines changed

1 file changed

+67
-34
lines changed

src/ws_dissector_helper.lua

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,48 @@ local Field = {}
99

1010
Field.repo = {}
1111

12+
-- Returns a ProtoField from the Field.repo. If it does not exist,
13+
-- it is first created and added to the repo.
1214
local function createProtoField(abbr, name, desc, len, type)
1315
local len = len or ''
14-
local type = type or ftypes.STRING
16+
local len = len or ''
17+
local type = type or 'STRING'
18+
19+
local ftype = nil
20+
if type == 'NUMERIC' then
21+
ftype = ftypes.FLOAT
22+
else
23+
ftype = ftypes.STRING
24+
end
25+
26+
local repoFieldName = abbr
27+
local f = Field.repo[repoFieldName]
1528

16-
local protoField = Field.repo[abbr .. len]
17-
if not protoField then
18-
--protoField = ProtoField.string(abbr, name, desc)
19-
protoField = ProtoField.new(name, abbr, type, nil, nil, nil, descr)
20-
Field.repo[abbr .. len] = protoField
29+
-- If a field with the same abbr exists in the repo we need to check
30+
-- the type and length as well. All three should much. Otherwise we
31+
-- need to create a new ProtoField.
32+
if f and f.len ~= len then
33+
warn('A field with name ' .. f.name .. ' and different length already exists.')
34+
repoFieldName = repoFieldName .. len
35+
f = Field.repo[repoFieldName]
36+
end
37+
38+
local protoField = nil
39+
40+
if f then
41+
protoField = f.protoField
42+
else
43+
--print(repoFieldName)
44+
protoField = ProtoField.new(name, repoFieldName, ftype, nil, nil, nil, descr)
45+
--print('ok')
46+
Field.repo[repoFieldName] = { name = name,
47+
abbr = abbr,
48+
len = len,
49+
ftype = ftype,
50+
descr = descr,
51+
protoField = protoField }
2152
end
53+
2254
return protoField
2355
end
2456

@@ -77,7 +109,7 @@ end
77109

78110
function Field.NUMERIC(len, abbr, name, desc, offset)
79111
return {
80-
proto = createProtoField(abbr, name, desc, len, ftypes.FLOAT),
112+
proto = createProtoField(abbr, name, desc, len, 'NUMERIC'),
81113
type = 'NUMERIC',
82114
len = function()
83115
return len
@@ -104,7 +136,7 @@ end
104136

105137
function Field.VARLEN(lenField, abbr, name, desc, offset)
106138
return {
107-
proto = createProtoField(abbr, name, desc),
139+
proto = createProtoField(abbr, name, desc, lenField.abbr),
108140
type = 'STRING',
109141
lenField = lenField,
110142
len = function(self, tvb)
@@ -282,36 +314,37 @@ local msgSpecToFieldSpec = function(id, description, msgSpec, header, trailer)
282314
-- Create Field.X object for each field in the spec
283315
local bodyFields = {}
284316
for i, f in ipairs(msgSpec) do
285-
-- Handle simple types.
286-
if tonumber(f.len) then
287-
local newField = nil
317+
-- Handle simple types.
318+
if f.fieldType == 'NUMERIC' then
319+
bodyFields[#bodyFields + 1] = Field.NUMERIC(f.len, f.abbr, f.name, '', f.offset)
320+
elseif f.fieldType == 'REPEATING' then
321+
local lenField = fieldByAbbr(f.len, bodyFields)
322+
assert(lenField, f.len .. ' does not match an existing abbr in message ' .. id)
288323

289-
if f.fieldType == 'NUMERIC' then
290-
newField = Field.NUMERIC(f.len, f.abbr, f.name, '', f.offset)
291-
else
292-
newField = Field.STRING(f.len, f.abbr, f.name, '', f.offset)
324+
local repeatingFields = {}
325+
for ii = i + 1, #msgSpec do
326+
local ff = msgSpec[ii]
327+
if ff.fieldType == 'REPEATING-END' then
328+
329+
end
330+
repeatingFields[#repeatingFields + 1] = Field.STRING(ff.len, ff.abbr, ff.name, '', ff.offset)
293331
end
332+
repeatingFields['title'] = f.name
294333

295-
bodyFields[#bodyFields + 1] = newField
296-
else -- Hanlde complex types
334+
local repeatingComposite = Field.COMPOSITE(repeatingFields)
335+
bodyFields[#bodyFields + 1] = Field.REPEATING(lenField, repeatingComposite)
336+
break
337+
elseif f.fieldType == 'VARLEN' then
297338
local lenField = fieldByAbbr(f.len, bodyFields)
298339
assert(lenField, f.len .. ' does not match an existing abbr in message ' .. id)
299340

300-
if f.fieldType == 'REPEATING' then
301-
local repeatingFields = {}
302-
for ii = i + 1, #msgSpec do
303-
local ff = msgSpec[ii]
304-
repeatingFields[#repeatingFields + 1] = Field.STRING(ff.len, ff.abbr, ff.name, '', ff.offset)
305-
end
306-
repeatingFields['title'] = f.name
307-
308-
local repeatingComposite = Field.COMPOSITE(repeatingFields)
309-
bodyFields[#bodyFields + 1] = Field.REPEATING(lenField, repeatingComposite)
310-
break
311-
elseif f.fieldType == 'VARLEN' then
312-
bodyFields[#bodyFields + 1] = Field.VARLEN(lenField, f.abbr, f.name, '', f.offset)
313-
break
314-
end
341+
bodyFields[#bodyFields + 1] = Field.VARLEN(lenField,
342+
f.abbr,
343+
f.name,
344+
'',
345+
f.offset)
346+
else -- Everything else will become Field.STRING
347+
bodyFields[#bodyFields + 1] = Field.STRING(f.len, f.abbr, f.name, '', f.offset)
315348
end
316349
end
317350
bodyFields['title'] = 'Body'
@@ -479,9 +512,9 @@ local function createProtoHelper(proto)
479512
msgParsers[v.name] = self:createParser(msgSpecs[v.name])
480513
end
481514

482-
for i, protoField in pairs(Field.repo) do
515+
for i, f in pairs(Field.repo) do
483516
self:trace('Adding ' .. i .. ' to proto.fields')
484-
table.insert(self.protocol.fields, protoField)
517+
table.insert(self.protocol.fields, f.protoField)
485518
end
486519

487520
self.header = header

0 commit comments

Comments
 (0)