dissector_itlc.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. local itlc = Proto("ITLC", "ITL Chorus Protocol")
  2. local fields = {
  3. command = ProtoField.new("Command", "itlc.cmd", ftypes.UINT32),
  4. pingdata = ProtoField.new("Ping Data", "itlc.ping", ftypes.BYTES),
  5. seconds = ProtoField.new("Seconds", "itlc.secs", ftypes.UINT32),
  6. microseconds = ProtoField.new("Microseconds", "itlc.usecs", ftypes.UINT32),
  7. frequency = ProtoField.new("Frequency(Hz)", "itlc.freq", ftypes.UINT32),
  8. amplitude = ProtoField.new("Amplitude", "itlc.amp", ftypes.FLOAT),
  9. port = ProtoField.new("Port", "itlc.port", ftypes.UINT32),
  10. ports = ProtoField.new("Ports", "itlc.ports", ftypes.UINT32),
  11. type = ProtoField.new("Client Type", "itlc.type", ftypes.STRING),
  12. ident = ProtoField.new("Client ID", "itlc.ident", ftypes.STRING),
  13. pcm = ProtoField.new("PCM Data", "itlc.pcm", ftypes.INT16),
  14. data = ProtoField.new("Unknown Data", "itlc.data", ftypes.BYTES),
  15. buffered = ProtoField.new("Buffered Samples", "itlc.buffered", ftypes.UINT32),
  16. artp = ProtoField.new("Articulation Parameter", "itlc.artp", ftypes.UINT32),
  17. value = ProtoField.new("Value", "itlc.value", ftypes.FLOAT),
  18. isglobal = ProtoField.new("Global?", "itlc.global", ftypes.BOOLEAN),
  19. }
  20. local fieldarray = {}
  21. for _, v in pairs(fields) do table.insert(fieldarray, v) end
  22. itlc.fields = fieldarray
  23. local commands = {
  24. [0] = "KA (keep alive)",
  25. [1] = "PING",
  26. [2] = "QUIT",
  27. [3] = "PLAY",
  28. [4] = "CAPS",
  29. [5] = "PCM",
  30. [6] = "PCMSYN",
  31. [7] = "ARTP",
  32. }
  33. setmetatable(commands, {__index = function(self, k) return "(Unknown command!)" end})
  34. local subdis = {
  35. [0] = function(buffer, tree) end, -- Nothing interesting...
  36. [1] = function(buffer, tree)
  37. tree:add(fields.pingdata, buffer())
  38. end,
  39. [2] = function(buffer, tree) end, -- Nothing interesting...
  40. [3] = function(buffer, tree, pinfo)
  41. tree:add(fields.seconds, buffer(0, 4))
  42. tree:add(fields.microseconds, buffer(4, 4))
  43. local freq = buffer(8, 4):uint()
  44. local fr = tree:add(fields.frequency, buffer(8, 4))
  45. tree:add(fields.amplitude, buffer(12, 4))
  46. tree:add(fields.port, buffer(16, 4))
  47. local midi = 12 * math.log(freq / 440.0) / math.log(2) + 69
  48. fr:append_text(" [MIDI pitch approx. " .. midi .. "]")
  49. pinfo.cols.info = tostring(pinfo.cols.info) .. string.format(" freq=%d (MIDI %f) amp=%f dur=%f port=%d", freq, midi, buffer(12,4):float(), buffer(0, 4):uint() + 0.000001 * buffer(4, 4):uint(), buffer(16, 4):uint())
  50. end,
  51. [4] = function(buffer, tree, pinfo)
  52. local pt = tree:add(fields.ports, buffer(0, 4))
  53. if buffer(0,4):uint() == 0 then
  54. pt:append_text(" [probably a request from the broadcaster]")
  55. pinfo.cols.info = tostring(pinfo.cols.info) .. " [request]"
  56. else
  57. pinfo.cols.info = tostring(pinfo.cols.info) .. string.format(" type=%q uid=%q", buffer(4, 4):string(), buffer(8):string())
  58. end
  59. tree:add(fields.type, buffer(4, 4))
  60. tree:add(fields.ident, buffer(8))
  61. end,
  62. [5] = function(buffer, tree)
  63. tree:add(fields.pcm, buffer())
  64. end,
  65. [6] = function(buffer, tree)
  66. tree:add(fields.buffered, buffer(4, 4):uint())
  67. end,
  68. [7] = function(buffer, tree, pinfo)
  69. local voice = buffer(4, 4):uint()
  70. local glob = (voice == 0xffffffff)
  71. tree:add(fields.port, voice)
  72. tree:add(fields.isglobal, glob)
  73. local artp = buffer(8, 4):uint()
  74. local val = buffer(12, 4):float()
  75. local fr = tree:add(fields.artp, artp)
  76. if glob then
  77. fr:append_text(" (Global)")
  78. pinfo.cols.info = tostring(pinfo.cols.info) .. " GART(" .. artp .. ") = " .. val
  79. else
  80. fr:append_text(" (Local)")
  81. pinfo.cols.info = tostring(pinfo.cols.info) .. " LART[" .. voice .. "](" .. artp .. ") = " .. val
  82. end
  83. tree:add(fields.value, val)
  84. end,
  85. }
  86. setmetatable(subdis, {__index = function(self, k) return function(buffer, tree)
  87. tree:add(fields.data, buffer())
  88. end end})
  89. function itlc.dissector(buffer, pinfo, tree)
  90. pinfo.cols.protocol = "ITLC"
  91. local st = tree:add(itlc, buffer(), "ITL Chorus Packet")
  92. local cmd = buffer(0,4):uint()
  93. st:add(fields.command, buffer(0,4), cmd, "Command: " .. commands[cmd] .. "(" .. cmd .. ")")
  94. pinfo.cols.info = commands[cmd]
  95. subdis[cmd](buffer(4):tvb(), st, pinfo)
  96. end
  97. local udp = DissectorTable.get("udp.port")
  98. udp:add(13676, itlc)
  99. udp:add(13677, itlc)
  100. print('ITLC dissector loaded!')