aboutsummaryrefslogtreecommitdiff
path: root/util/snowcast-dissector/cs168_snowcast.lua
blob: 511aa597dd4a6dde121f01c4933454e72c0af632 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
-- CS168 Snowcast Protocol Dissector

snowcast_protocol = Proto("CS168Snowcast", "CS168 Snowcast Protocol")

message = ProtoField.uint8("cs168snowcast.messsage_type", "messageType", base.DEC)

-- HELLO fields
udp_port = ProtoField.uint16("cs168snowcast.udp_port", "udpPort", base.DEC)
-- SET_STATION fields
station_number = ProtoField.uint16("cs168snowcast.station_number", "stationNumber", base.DEC)
-- WELCOME fields
num_stations = ProtoField.uint16("cs168snowcast.num_stations", "numStations", base.DEC)
-- ANNOUNCE fields
song_name_size = ProtoField.uint8("cs168snowcast.song_name_size", "songnameSize", base.DEC)
song_name = ProtoField.string("cs168snowcast.song_name", "songname")
-- INVALID_COMMAND fields
reply_string_size = ProtoField.uint8("cs168snowcast.reply_string_size", "replyStringSize", base.DEC)
reply_string = ProtoField.string("cs168snowcast.reply_string", "replyString")

snowcast_protocol.fields = {
  message,
  udp_port,
  station_number,
  num_stations,
  song_name_size,
  song_name,
  reply_string_size,
  reply_string
}

function snowcast_protocol.dissector(buffer, pinfo, tree)
  length = buffer:len()
  if length == 0 then return end

  pinfo.cols.protocol = snowcast_protocol.name

  local subtree = tree:add(snowcast_protocol, buffer(), "Snowcast Protocol Data")

  local packet_len = buffer:reported_length_remaining()

  local message_num = buffer(0, 1):uint()
  local message_name = get_message_name(message_num)

  -- Add command ID and name
  subtree:add(message, buffer(0, 1)):append_text(" (" .. message_name .. ") ")

  -- Clear any existing info in the info column so the TCP stuff info isn't in the way
  pinfo.cols.info = ""

  pinfo.cols.info:append("Snowcast " .. message_name)

  if message_num == 0 then
    -- Handling HELLO command
    local udpPort = buffer(1, 2):uint()
    subtree:add(udp_port, buffer(1, 2))
    pinfo.cols.info:append(" (UDP Port: " .. udpPort .. ") ")
  elseif message_num == 1 then
    -- Handling SET_STATION command
    local stationNumber = buffer(1, 2):uint()
    subtree:add(station_number, buffer(1, 2))
    pinfo.cols.info:append(" (Station Number: " .. stationNumber .. ") ")
  elseif message_num == 2 then
    -- Handling WELCOME reply
    local numStations = buffer(1, 2):uint()
    subtree:add(num_stations, buffer(1, 2))
    pinfo.cols.info:append(" (Station Number: " .. numStations .. ") ")
  elseif message_num == 3 then
    -- Handling ANNOUNCE reply
    local songnameSize = buffer(1, 1):uint()
    subtree:add(reply_string_size, buffer(1, 1))

    local songname = buffer(2, songnameSize):string()
    subtree:add(reply_string, buffer(2, songnameSize))

    pinfo.cols.info:append(" (Song Name [" .. songnameSize .. " bytes]: " .. songname .. ") ")
  elseif message_num == 4 then
    -- Handling INVALID_COMMAND reply
    local replyStringSize = buffer(1, 1):uint()
    subtree:add(reply_string_size, buffer(1, 1))

    local replyString = buffer(2, replyStringSize):string()
    subtree:add(reply_string, buffer(2, replyStringSize))

    pinfo.cols.info:append(" (Reply String [" .. replyStringSize .. " bytes]: " .. replyString .. ") ")
  end
end

function get_message_name(message_num)
  local message_name = "UNNOWN"

  if message_num == 0 then
    message_name = "HELLO"
  elseif message_num == 1 then
    message_name = "SET_STATION"
  elseif message_num == 2 then
    message_name = "WELCOME REPLY"
  elseif message_num == 3 then
    message_name = "ANNOUNCE REPLY"
  elseif message_num == 4 then
    message_name = "INVALID_COMMAND REPLY"
  end

  return message_name
end

local tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(1680, snowcast_protocol)