1-- @brief srt-dev Protocol dissector plugin
2
3-- create a new dissector
4local NAME = "SRT-dev"
5local srt_dev = Proto(NAME, "SRT-dev Protocol")
6
7-- create a preference of a Protocol
8srt_dev.prefs["srt_udp_port"] = Pref.uint("SRT UDP Port", 1935, "SRT UDP Port")
9
10-- create fields of srt_dev
11-- Base.HEX, Base.DEC, Base.OCT, Base.UNIT_STRING, Base.NONE
12local fields = srt_dev.fields
13-- General field
14local pack_type_select = {
15	[0] = "Data Packet",
16	[1] = "Control Packet"
17}
18fields.pack_type_tree = ProtoField.uint32(NAME .. ".pack_type_tree", "Packet Type", base.HEX)
19fields.pack_type = ProtoField.uint16("srt_dev.pack_type", "Packet Type", base.HEX, pack_type_select, 0x8000)
20fields.reserve = ProtoField.uint16("srt_dev.reserve", "Reserve", base.DEC)
21fields.additional_info = ProtoField.uint32("srt_dev.additional_info", "Additional Information", base.DEC)
22fields.time_stamp = ProtoField.uint32("srt_dev.time_stamp", "Time Stamp", base.DEC)
23fields.dst_sock = ProtoField.uint32("srt_dev.dst_sock", "Destination Socket ID", base.DEC)
24fields.none = ProtoField.none("srt_dev.none", "none", base.NONE)
25
26-- Data packet fields
27fields.data_flag_info_tree = ProtoField.uint8("srt_dev.data_flag_info_tree", "Data Flag Info", base.HEX)
28local FF_state_select = {
29	[0] = "[Middle packet]",
30	[1] = "[Last packet]",
31	[2] = "[First packet]",
32	[3] = "[Single packet]"
33}
34fields.FF_state = ProtoField.uint8("srt_dev.FF_state", "FF state", base.HEX, FF_state_select, 0xC0)
35local O_state_select = {
36	[0] = "[ORD_RELAX]",
37	[1] = "[ORD_REQUIRED]"
38}
39fields.O_state = ProtoField.uint8("srt_dev.O_state", "O state", base.HEX, O_state_select, 0x20)
40local KK_state_select = {
41	[0] = "[Not encrypted]",
42	[1] = "[Data encrypted with even key]",
43	[2] = "[Data encrypted with odd key]"
44}
45fields.KK_state = ProtoField.uint8("srt_dev.KK_state", "KK state", base.HEX, KK_state_select, 0x18)
46local R_state_select = {
47	[0] = "[ORIGINAL]",
48	[1] = "[RETRANSMITTED]"
49}
50fields.R_state = ProtoField.uint8("srt_dev.R_state", "R state", base.HEX, R_state_select, 0x04)
51fields.seq_num = ProtoField.uint32("srt_dev.seq_num", "Sequence Number", base.DEC)
52fields.msg_num = ProtoField.uint32("srt_dev.msg_num", "Message Number", base.DEC)--, nil, 0x3FFFFFF)
53
54-- control packet fields
55local msg_type_select = {
56	[0] = "[HANDSHAKE]",
57	[1] = "[KEEPALIVE]",
58	[2] = "[ACK]",
59	[3] = "[NAK(Loss Report)]",
60	[4] = "[Congestion Warning]",
61	[5] = "[Shutdown]",
62	[6] = "[ACKACK]",
63	[7] = "[Drop Request]",
64	[8] = "[Peer Error]",
65	[0x7FFF] = "[Message Extension Type]"
66}
67fields.msg_type = ProtoField.uint16("srt_dev.msg_type", "Message Type", base.HEX, msg_type_select, 0x7FFF)
68fields.msg_ext_type = ProtoField.uint16("srt_dev.msg_ext_type", "Message Extented Type", base.DEC)
69
70local flag_state_select = {
71	[0] = "Unset",
72	[1] = "Set"
73}
74
75-- Handshake packet fields
76fields.UDT_version = ProtoField.uint32("srt_dev.UDT_version", "UDT Version", base.DEC)
77fields.sock_type = ProtoField.uint32("srt_dev.sock_type", "Socket Type", base.DEC)
78fields.ency_fld = ProtoField.uint16("srt_dev.ency_fld", "Encryption Field", base.DEC)
79fields.ext_fld = ProtoField.uint16("srt_dev.ext_fld", "Extension Fields", base.HEX)
80fields.ext_fld_tree = ProtoField.uint16("srt_dev.ext_fld_tree", "Extension Fields Tree", base.HEX)
81fields.hsreq = ProtoField.uint16("srt_dev.hsreq", "HS_EXT_HSREQ", base.HEX, flag_state_select, 0x1)
82fields.kmreq = ProtoField.uint16("srt_dev.kmreq", "HS_EXT_KMREQ", base.HEX, flag_state_select, 0x2)
83fields.config = ProtoField.uint16("srt_dev.config", "HS_EXT_CONFIG", base.HEX, flag_state_select, 0x4)
84fields.isn = ProtoField.uint32("srt_dev.isn", "Initial packet sequence number", base.DEC)
85fields.mss = ProtoField.uint32("srt_dev.mss", "Max Packet Size", base.DEC)
86fields.fc = ProtoField.uint32("srt_dev.fc", "Maximum Flow Window Size", base.DEC)
87fields.conn_type = ProtoField.int32("srt_dev.conn_type", "Connection Type", base.DEC)
88fields.sock_id = ProtoField.uint32("srt_dev.sock_id", "Socket ID", base.DEC)
89fields.syn_cookie = ProtoField.uint32("srt_dev.syn_cookie", "SYN cookie", base.DEC)
90fields.peer_ipaddr = ProtoField.none("srt_dev.peer_ipaddr", "Peer IP address", base.NONE)
91fields.peer_ipaddr_4 = ProtoField.ipv4("srt_dev.peer_ipaddr", "Peer IP address")
92fields.peer_ipaddr_6 = ProtoField.ipv6("srt_dev.peer_ipaddr", "Peer IP address")
93local ext_type_select = {
94	[-1] = "SRT_CMD_NONE",
95	[0] = "SRT_CMD_REJECT",
96	[1] = "SRT_CMD_HSREQ",
97	[2] = "SRT_CMD_HSRSP",
98	[3] = "SRT_CMD_KMREQ",
99	[4] = "SRT_CMD_KMRSP",
100	[5] = "SRT_CMD_SID",
101	[6] = "SRT_CMD_CONGESTION",
102	[7] = "SRT_CMD_FILTER",
103	[8] = "SRT_CMD_GROUP"
104}
105fields.ext_type_msg_tree = ProtoField.none("srt_dev.ext_type", "Extension Type Message", base.NONE)
106fields.ext_type = ProtoField.uint16("srt_dev.ext_type", "Extension Type", base.HEX, ext_type_select, 0xF)
107fields.ext_size = ProtoField.uint16("srt_dev.ext_size", "Extension Size", base.DEC)
108
109-- Handshake packet, ext type == SRT_CMD_HSREQ or SRT_CMD_HSRSP field
110fields.srt_version = ProtoField.uint32("srt_dev.srt_version", "SRT Version", base.HEX)
111fields.srt_flags = ProtoField.uint32("srt_dev.srt_flags", "SRT Flags", base.HEX)
112fields.tsbpb_resv = ProtoField.uint16("srt_dev.tsbpb_resv", "TsbPb Receive", base.DEC)
113fields.tsbpb_delay = ProtoField.uint16("srt_dev.tsbpb_delay", "TsbPb Delay", base.DEC)
114fields.tsbpd_delay = ProtoField.uint16("srt_dev.tsbpd_delay", "TsbPd Delay", base.DEC)
115fields.rcv_tsbpd_delay = ProtoField.uint16("srt_dev.rcv_tsbpd_delay", "Receiver TsbPd Delay", base.DEC)
116fields.snd_tsbpd_delay = ProtoField.uint16("srt_dev.snd_tsbpd_delay", "Sender TsbPd Delay", base.DEC)
117
118-- V adn PT status flag
119local V_state_select = {
120	[1] = "Initial version"
121}
122fields.V_state = ProtoField.uint8("srt_dev.V_state", "V", base.HEX, V_state_select, 0x70)
123local PT_state_select = {
124	[0] = "Reserved",
125	[1] = "MSmsg",
126	[2] = "KMmsg",
127	[7] = "Reserved to discriminate MPEG-TS packet(0x47=sync byte)"
128}
129fields.PT_state = ProtoField.uint8("srt_dev.PT_state", "PT", base.HEX, state_table, 0xF)
130fields.sign = ProtoField.uint16("srt_dev.sign", "Signature", base.HEX)
131local resv_select = {
132	[0] = "Reserved for flag extension or other usage"
133}
134fields.resv = ProtoField.uint8("srt_dev.resv", "Resv", base.DEC, state_table, 0xFC)
135fields.ext_KK_state = ProtoField.uint8("srt_dev.ext_KK_state", "KK_state", base.HEX, KK_state_select, 0x3)
136fields.KEKI = ProtoField.uint32("srt_dev.KEKI", "KEKI", base.DEC)
137fields.cipher = ProtoField.uint8("srt_dev.cipher", "Cipher", base.DEC)
138fields.auth = ProtoField.uint8("srt_dev.auth", "auth", base.DEC)
139fields.SE = ProtoField.uint8("srt_dev.SE", "SE", base.DEC)
140fields.resv1 = ProtoField.uint8("srt_dev.resv1", "resv1", base.DEC)
141fields.resv2 = ProtoField.uint16("srt_dev.resv2", "resv2", base.DEC)
142fields.slen = ProtoField.uint8("srt_dev.slen", "Salt length(bytes)/4", base.DEC)
143fields.klen = ProtoField.uint8("srt_dev.klen", "SEK length(bytes)/4", base.DEC)
144fields.salt = ProtoField.uint32("srt_dev.salt", "Salt key", base.DEC)
145fields.wrap = ProtoField.none("srt_dev.wrap", "Wrap key(s)", base.NONE)
146
147-- Wrap Field
148fields.ICV = ProtoField.uint64("srt_dev.ICV", "Integerity Check Vector", base.HEX)
149fields.odd_key = ProtoField.stringz("srt_dev.odd_key", "Odd key", base.ASCII)
150fields.even_key = ProtoField.stringz("srt_dev.even_key", "Even key", base.ASCII)
151
152-- ext_type == SRT_CMD_SID field
153fields.sid = ProtoField.string("srt_dev.sid", "Stream ID", base.ASCII)
154-- ext_type == SRT_CMD_CONGESTION field
155fields.congestion = ProtoField.string("srt_dev.congestion", "Congestion Controller", base.ASCII)
156-- ext_type == SRT_CMD_FILTER field
157fields.filter = ProtoField.string("srt_dev.filter", "Filter", base.ASCII)
158-- ext_type == SRT_CMD_GROUP field
159fields.group = ProtoField.string("srt_dev.group", "Group Data", base.ASCII)
160
161-- SRT flags
162fields.srt_opt_tsbpdsnd = ProtoField.uint32("srt_dev.srt_opt_tsbpdsnd", "SRT_OPT_TSBPDSND", base.HEX, flag_state_select, 0x1)
163fields.srt_opt_tsbpdrcv = ProtoField.uint32("srt_dev.srt_opt_tsbpdrcv", "SRT_OPT_TSBPDRCV", base.HEX, flag_state_select, 0x2)
164fields.srt_opt_haicrypt = ProtoField.uint32("srt_dev.srt_opt_haicrypt", "SRT_OPT_HAICRYPT", base.HEX, flag_state_select, 0x4)
165fields.srt_opt_tlpktdrop = ProtoField.uint32("srt_dev.srt_opt_tlpktdrop", "SRT_OPT_TLPKTDROP", base.HEX, flag_state_select, 0x8)
166fields.srt_opt_nakreport = ProtoField.uint32("srt_dev.srt_opt_nakreport", "SRT_OPT_NAKREPORT", base.HEX, flag_state_select, 0x10)
167fields.srt_opt_rexmitflg = ProtoField.uint32("srt_dev.srt_opt_rexmitflg", "SRT_OPT_REXMITFLG", base.HEX, flag_state_select, 0x20)
168fields.srt_opt_stream = ProtoField.uint32("srt_dev.srt_opt_stream", "SRT_OPT_STREAM", base.HEX, flag_state_select, 0x40)
169
170-- ACK fields
171fields.last_ack_pack = ProtoField.uint32("srt_dev.last_ack_pack", "Last ACK Packet Sequence Number", base.DEC)
172fields.rtt = ProtoField.int32("srt_dev.rtt", "Round Trip Time", base.DEC)
173fields.rtt_variance = ProtoField.int32("srt_dev.rtt_variance", "Round Trip Time Variance", base.DEC)
174fields.buf_size = ProtoField.uint32("srt_dev.buf_size", "Available Buffer Size", base.DEC)
175fields.pack_rcv_rate = ProtoField.uint32("srt_dev.pack_rcv_rate", "Packet Receiving Rate", base.DEC)
176fields.est_link_capacity = ProtoField.uint32("srt_dev.est_link_capacity", "Estimated Link Capacity", base.DEC)
177fields.rcv_rate = ProtoField.uint32("srt_dev.rcv_rate", "Receiving Rate", base.DEC)
178
179-- ACKACK fields
180fields.ack_num = ProtoField.uint32("srt_dev.ack_num", "ACK number", base.DEC)
181fields.ctl_info = ProtoField.uint32("srt_dev.ctl_info", "Control Information", base.DEC)
182
183-- KMRSP fields
184local srt_km_state_select = {
185	[0] = "[SRT_KM_UNSECURED]",
186	[1] = "[SRT_KM_SECURING]",
187	[2] = "[SRT_KM_SECURED]",
188	[3] = "[SRT_KM_NOSECRET]",
189	[4] = "[SRT_KM_BADSECRET]"
190}
191fields.km_err = ProtoField.uint32("srt_dev.km_err", "Key Message Error", base.HEX, srt_km_state_select, 0xF)
192
193-- NAK Control Packet fields
194fields.lost_list_tree = ProtoField.none("srt_dev.lost_list_tree", "Lost Packet List", base.NONE)
195fields.lost_pack_seq = ProtoField.uint32("srt_dev.lost_pack_seq", "Lost Packet Sequence Number", base.DEC)
196fields.lost_pack_range_tree = ProtoField.none("srt_dev.lost_pack_range_tree", "Lost Packet Range", base.NONE)
197fields.lost_start = ProtoField.uint32("srt_dev.lost_start", "Lost Starting Sequence", base.DEC)
198fields.lost_up_to = ProtoField.uint32("srt_dev.lost_up_to", "Lost Up To(including)", base.DEC)
199
200-- Dissect packet
201function srt_dev.dissector (tvb, pinfo, tree)
202	-- Packet is based on UDP, so the data can be processed directly after UDP
203	local subtree = tree:add(srt_dev, tvb())
204	local offset = 0
205
206	-- Changes the protocol name
207	pinfo.cols.protocol = srt_dev.name
208
209	-- Take out the first bit of package
210	-- 0 -> Data Packet
211	-- 1 -> Control Packet
212	local typebit = bit.rshift(tvb(offset, 1):uint(), 7)
213	pack_type_tree = subtree:add(fields.pack_type_tree, tvb(offset, 4))
214
215	if typebit == 1 then
216		-- Handle Control Packet
217		pack_type_tree:add(fields.pack_type, tvb(offset, 2))
218
219		local msg_type = tvb(offset, 2):uint()
220		if msg_type ~= 0xFFFF then
221			-- If type field isn't '0x7FFF',it means packet is normal data packet, then handle type field
222			msg_type = bit.band(msg_type, 0x7FFF)
223
224			function parse_three_param()
225				-- Ignore Additional Info (this field is not defined in this packet type)
226				subtree:add(fields.additional_info, tvb(offset, 4)):append_text(" [undefined]")
227				offset = offset + 4
228
229				-- Handle Time Stamp
230				subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
231				offset = offset + 4
232
233				-- Handle Destination Socket
234				subtree:add(fields.dst_sock, tvb(offset, 4))
235				offset = offset + 4
236			end
237
238			local switch = {
239				[0] = function()
240					pinfo.cols.info:append(" [HANDSHAKE]")
241					pack_type_tree:append_text(" [HANDSHAKE]")
242					pack_type_tree:add(fields.msg_type, tvb(offset, 2))
243					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
244					offset = offset + 4
245
246					-- Handle Additional Info, Timestamp and Destination Socket
247					parse_three_param()
248
249					-- Handle UDT version field
250					local UDT_version = tvb(offset, 4):uint()
251					subtree:add(fields.UDT_version, tvb(offset, 4))
252					offset = offset + 4
253
254					if UDT_version == 4 then
255						-- UDT version is 4, packet is diffrent from UDT version 5
256						-- Handle sock type
257						local sock_type = tvb(offset, 4):uint()
258						if sock_type == 1 then
259							subtree:add(fields.sock_type, tvb(offset, 4)):append_text(" [SRT_STREAM]")
260						elseif sock_type == 2 then
261							subtree:add(fields.sock_type, tvb(offset, 4)):append_text(" [SRT_DRAGAM]")
262						end
263						offset = offset + 4
264					elseif UDT_version == 5 then
265						-- Handle Encryption Field
266						local encr_fld = tvb(offset, 2):int()
267						if encr_fld == 0 then
268							subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (PBKEYLEN not advertised)")
269						elseif encr_fld == 2 then
270							subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (AES-128)")
271						elseif encr_fld == 3 then
272							subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (AES-192)")
273						else
274							subtree:add(fields.ency_fld, tvb(offset, 2)):append_text(" (AES-256)")
275						end
276						offset = offset + 2
277
278						-- Handle Extension Field
279						local ext_fld = tvb(offset, 2):int()
280						if ext_fld == 0x4A17 then
281							subtree:add(fields.ext_fld, tvb(offset, 2)):append_text(" [HSv5 MAGIC]")
282						else
283							-- Extension Field is HS_EXT_prefix
284							-- The define is in fiel handshake.h
285							local ext_fld_tree = subtree:add(fields.ext_fld_tree, tvb(offset, 2))
286							local str_table = { " [" }
287							ext_fld_tree:add(fields.hsreq, tvb(offset, 2))
288							if bit.band(tvb(offset, 2):uint(), 0x1) == 1 then
289								table.insert(str_table, "HS_EXT_HSREQ")
290								table.insert(str_table, " | ")
291							end
292							ext_fld_tree:add(fields.kmreq, tvb(offset, 2)):append_text(" [HS_EXT_KMREQ]")
293							if bit.band(tvb(offset, 2):uint(), 0x2) == 2 then
294								table.insert(str_table, "HS_EXT_KMREQ")
295								table.insert(str_table, " | ")
296							end
297							ext_fld_tree:add(fields.config, tvb(offset, 2)):append_text(" [HS_EXT_CONFIG]")
298							if bit.band(tvb(offset, 2):uint(), 0x4) == 4 then
299								table.insert(str_table, "HS_EXT_CONFIG")
300								table.insert(str_table, " | ")
301							end
302							table.remove(str_table)
303							table.insert(str_table, "]")
304							if ext_fld ~= 0 then
305								ext_fld_tree:append_text(table.concat(str_table))
306							end
307						end
308						offset = offset + 2
309					end
310
311					-- Handle Initial packet sequence number
312					subtree:add(fields.isn, tvb(offset, 4))
313					offset = offset + 4
314
315					-- Handle Maximum Packet Size
316					subtree:add(fields.mss, tvb(offset, 4))
317					offset = offset + 4
318
319					-- Handle Maximum Flow Window Size
320					subtree:add(fields.fc, tvb(offset, 4))
321					offset = offset + 4
322
323					-- Handle Connection Type
324					local conn_type = tvb(offset, 4):int()
325					local conn_type_tree = subtree:add(fields.conn_type, tvb(offset, 4))
326					if conn_type == 0 then
327						conn_type_tree:append_text(" [WAVEAHAND] (Rendezvous Mode)")
328						pinfo.cols.info:append(" [WAVEAHAND] (Rendezvous Mode)")
329					elseif conn_type == 1 then
330						conn_type_tree:append_text(" [INDUCTION]")
331					elseif conn_type == -1 then
332						conn_type_tree:append_text(" [CONCLUSION]")
333					elseif conn_type == -2 then
334						conn_type_tree:append_text(" [AGREEMENT] (Rendezvous Mode)")
335						pinfo.cols.info:append(" [AGREEMENT] (Rendezvous Mode)")
336					end
337					offset = offset + 4
338
339					-- Handle Socket ID
340					subtree:add(fields.sock_id, tvb(offset, 4))
341					offset = offset + 4
342
343					-- Handle SYN cookie
344					local syn_cookie = tvb(offset, 4):int()
345					subtree:add(fields.syn_cookie, tvb(offset, 4))
346					if syn_cookie == 0 then
347						conn_type_tree:append_text(" (Caller to Listener)")
348						pinfo.cols.info:append(" (Caller to Listener)")
349					else
350						if conn_type == 1 then
351							-- reports cookie from listener
352							conn_type_tree:append_text(" (Listener to Caller)")
353							pinfo.cols.info:append(" (Listener to Caller)")
354						end
355					end
356					offset = offset + 4
357
358					-- Handle Peer IP address
359					-- Note the network byte order
360					local the_last_96_bits = 0
361					the_last_96_bits = the_last_96_bits + math.floor(tvb(offset + 4, 4):int() * (2 ^ 16))
362					the_last_96_bits = the_last_96_bits + math.floor(tvb(offset + 8, 4):int() * (2 ^ 8))
363					the_last_96_bits = the_last_96_bits + tvb(offset + 12, 4):int()
364					if the_last_96_bits == 0 then
365						subtree:add_le(fields.peer_ipaddr_4, tvb(offset, 4))
366					else
367						subtree:add_le(fields.peer_ipaddr, tvb(offset, 16))
368					end
369
370					offset = offset + 16
371
372					-- UDT version is 4, packet handle finish
373					if UDT_version == 4 or offset == tvb:len() then
374						return
375					end
376
377					function process_ext_type()
378						-- Handle Ext Type, processing by type
379						local ext_type = tvb(offset, 2):int()
380						if ext_type == 1 or ext_type == 2 then
381							local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, 16))
382							if ext_type == 1 then
383								ext_type_msg_tree:append_text(" [SRT_CMD_HSREQ]")
384								ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
385								conn_type_tree:append_text(" (Caller to Listener)")
386								pinfo.cols.info:append(" (Caller to Listener)")
387							else
388								ext_type_msg_tree:append_text(" [SRT_CMD_HSRSP]")
389								ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
390								conn_type_tree:append_text(" (Listener to Caller)")
391								pinfo.cols.info:append(" (Listener to Caller)")
392							end
393							offset = offset + 2
394
395							-- Handle Ext Size
396							ext_type_msg_tree:add(fields.ext_size, tvb(offset, 2))
397							offset = offset + 2
398
399							-- Handle SRT Version
400							ext_type_msg_tree:add(fields.srt_version, tvb(offset, 4))
401							offset = offset + 4
402
403							-- Handle SRT Flags
404							local SRT_flags_tree = ext_type_msg_tree:add(fields.srt_flags, tvb(offset, 4))
405							SRT_flags_tree:add(fields.srt_opt_tsbpdsnd, tvb(offset, 4))
406							SRT_flags_tree:add(fields.srt_opt_tsbpdrcv, tvb(offset, 4))
407							SRT_flags_tree:add(fields.srt_opt_haicrypt, tvb(offset, 4))
408							SRT_flags_tree:add(fields.srt_opt_tlpktdrop, tvb(offset, 4))
409							SRT_flags_tree:add(fields.srt_opt_nakreport, tvb(offset, 4))
410							SRT_flags_tree:add(fields.srt_opt_rexmitflg, tvb(offset, 4))
411							SRT_flags_tree:add(fields.srt_opt_stream, tvb(offset, 4))
412							offset = offset + 4
413
414							-- Handle Recv TsbPd Delay and Snd TsbPd Delay
415							if UDT_version == 4 then
416								ext_type_msg_tree:add(fields.tsbpd_delay, tvb(offset, 2)):append_text(" [Unused in HSv4]")
417								offset = offset + 2
418								ext_type_msg_tree:add(fields.tsbpb_delay, tvb(offset, 2))
419								offset = offset + 2
420							else
421								ext_type_msg_tree:add(fields.rcv_tsbpd_delay, tvb(offset, 2))
422								offset = offset + 2
423								ext_type_msg_tree:add(fields.snd_tsbpd_delay, tvb(offset, 2))
424								offset = offset + 2
425							end
426						elseif ext_type == 3 or ext_type == 4 then
427							local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, 16))
428							if ext_type == 3 then
429								ext_type_msg_tree:append_text(" [SRT_CMD_KMREQ]")
430								ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
431								conn_type_tree:append_text(" (Listener to Caller)")
432							else
433								ext_type_msg_tree:append_text(" [SRT_CMD_KMRSP]")
434								ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
435							end
436							offset = offset + 2
437
438							-- Handle Ext Size
439							local km_len = tvb(offset, 2):uint()
440							ext_type_msg_tree:add(fields.ext_size, tvb(offset, 2)):append_text(" (byte/4)")
441							offset = offset + 2
442
443							-- Handle SRT_CMD_KMREQ message
444							-- V and PT status flag
445							ext_type_msg_tree:add(fields.V_state, tvb(offset, 1))
446							ext_type_msg_tree:add(fields.PT_state, tvb(offset, 1))
447							offset = offset + 1
448
449							-- Handle sign
450							ext_type_msg_tree:add(fields.sign, tvb(offset, 2)):append_text(" (/'HAI/' PnP Vendor ID in big endian order)")
451							offset = offset + 2
452
453							-- Handle resv
454							ext_type_msg_tree:add(fields.resv, tvb(offset, 1))
455
456							-- Handle KK flag
457							local KK = tvb(offset, 1):uint()
458							ext_type_msg_tree:add(fields.ext_KK_state, tvb(offset, 1))
459							offset = offset + 1
460
461							-- Handle KEKI
462							if tvb(offset, 4):uint() == 0 then
463								ext_type_msg_tree:add(fields.KEKI, tvb(offset, 4)):append_text(" (Default stream associated key(stream/system default))")
464							else
465								ext_type_msg_tree:add(fields.KEKI, tvb(offset, 4)):append_text(" (Reserved for manually indexed keys)")
466							end
467							offset = offset + 4
468
469							-- Handle Cipher
470							local cipher_node = ext_type_msg_tree:add(fields.cipher, tvb(offset, 1))
471							local cipher = tvb(offset, 1):uint()
472							if cipher == 0 then
473							elseif cipher == 1 then
474								cipher_node:append_text(" (AES-ECB(potentially for VF 2.0 compatible message))")
475							elseif cipher == 2 then
476								cipher_node:append_text(" (AES-CTR[FP800-38A])")
477							else
478								cipher_node:append_text(" (AES-CCM or AES-GCM)")
479							end
480							offset = offset + 1
481
482							-- Handle Auth
483							if tvb(offset, 1):uint() == 0 then
484								ext_type_msg_tree:add(fields.auth, tvb(offset, 1)):append_text(" (None or KEKI indexed crypto context)")
485							else
486								ext_type_msg_tree:add(fields.auth, tvb(offset, 1))
487							end
488							offset = offset + 1
489
490							-- Handle SE
491							local SE_node = ext_type_msg_tree:add(fields.SE, tvb(offset, 1))
492							local SE = tvb(offset, 1):uint()
493							if SE == 0 then
494								SE_node:append_text( " (Unspecified or KEKI indexed crypto context)")
495							elseif SE == 1 then
496								SE_node:append_text( " (MPEG-TS/UDP)")
497							elseif SE == 2 then
498								SE_node:append_text( " (MPEG-TS/SRT)")
499							end
500							offset = offset + 1
501
502							-- Handle resv1
503							ext_type_msg_tree:add(fields.resv1, tvb(offset, 1))
504							offset = offset + 1
505
506							-- Handle resv2
507							ext_type_msg_tree:add(fields.resv2, tvb(offset, 2))
508							offset = offset + 2
509
510							-- Handle slen
511							ext_type_msg_tree:add(fields.slen, tvb(offset, 1))
512							offset = offset + 1
513
514							-- Handle klen
515							local klen = tvb(offset, 1):uint()
516							ext_type_msg_tree:add(fields.klen, tvb(offset, 1))
517							offset = offset + 1
518
519							-- Handle salt key
520							ext_type_msg_tree:add(fields.salt, tvb(offset, slen * 4))
521							offset = offset + slen * 4
522
523							-- Handle wrap
524							-- Handle ICV
525							local wrap_len = 8 + KK * klen
526							local wrap_tree = ext_type_msg_tree:add(fields.wrap, tvb(offset, wrap_len))
527							wrap_tree:add(fields.ICV, tvb(offset, 8))
528							offset = offset + 8
529							-- If KK == 2, first key is Even key
530							if KK == 2 then
531								wrap_tree:add(fields.even_key, tvb(offset, klen))
532								offset = offset + klen;
533							end
534
535							-- Handle Odd key
536							wrap_tree:add(fields.odd_key, tvb(offset, klen))
537							offset = offset + klen;
538						elseif ext_type >= 5 and ext_type <= 8 then
539							local value_size = tvb(offset + 2, 2):uint() * 4
540							local ext_msg_size = 2 + 2 + value_size
541							local type_array = { " [SRT_CMD_SID]", " [SRT_CMD_CONGESTION]", " [SRT_CMD_FILTER]", " [SRT_CMD_GROUP]" }
542							local field_array = { fields.sid, fields.congestion, fields.filter, fields.group }
543							local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, ext_msg_size)):append_text(type_array[ext_type - 4])
544							ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
545							offset = offset + 2
546
547							-- Handle Ext Msg Value Size
548							ext_type_msg_tree:add(fields.ext_size, tvb(offset, 2)):append_text(" (byte/4)")
549							offset = offset + 2
550
551							-- Value
552							local value_table = {}
553							for pos = 0, value_size - 4, 4 do
554								table.insert(value_table, string.char(tvb(offset + pos + 3, 1):uint()))
555								table.insert(value_table, string.char(tvb(offset + pos + 2, 1):uint()))
556								table.insert(value_table, string.char(tvb(offset + pos + 1, 1):uint()))
557								table.insert(value_table, string.char(tvb(offset + pos, 1):uint()))
558							end
559							local value = table.concat(value_table)
560							ext_type_msg_tree:add(field_array[ext_type - 4], tvb(offset, value_size), value)
561							offset = offset + value_size
562						elseif ext_type == -1 then
563							local ext_type_msg_tree = subtree:add(fields.ext_type_msg_tree, tvb(offset, tvb:len() - offset)):append_text(" [SRT_CMD_NONE]")
564							ext_type_msg_tree:add(fields.ext_type, tvb(offset, 2))
565							offset = offset + 2
566
567							-- none
568							if offset == tvb:len() then
569								return
570							end
571							ext_type_msg_tree:add(fields.none, tvb(offset, tvb:len() - offset))
572							offset = tvb:len()
573						end
574						if offset == tvb:len() then
575							return
576						else
577							process_ext_type()
578						end
579					end
580
581					process_ext_type()
582				end,
583				[1] = function()
584					pinfo.cols.info:append(" [KEEPALIVE]")
585					pack_type_tree:append_text(" [KEEPALIVE]")
586					pack_type_tree:add(fields.msg_type, tvb(offset, 2)):append_text(" [KEEPALIVE]")
587					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
588					offset = offset + 4
589
590					-- Handle Additional Info, Time Stamp and Destination Socket
591					parse_three_param()
592				end,
593				[2] = function()
594					pinfo.cols.info:append(" [ACK]")
595					pack_type_tree:append_text(" [ACK]")
596					pack_type_tree:add(fields.msg_type, tvb(offset, 2))
597					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
598					offset = offset + 4
599
600					-- Handle ACK Number
601					subtree:add(fields.ack_num, tvb(offset, 4))
602					offset = offset + 4
603
604					-- Handle Time Stamp
605					subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
606					offset = offset + 4
607
608					-- Handle Destination Socket
609					subtree:add(fields.dst_sock, tvb(offset, 4))
610					offset = offset + 4
611
612					-- Handle Last Ack Packet Sequence
613					local last_ack_pack = tvb(offset, 4):uint()
614					pinfo.cols.info:append(" (Last ACK Seq:" .. last_ack_pack .. ")")
615					subtree:add(fields.last_ack_pack, tvb(offset, 4))
616					offset = offset + 4
617
618					-- Handle RTT
619					local rtt = tvb(offset, 4):int()
620					subtree:add(fields.rtt, tvb(offset, 4)):append_text(" μs")
621					offset = offset + 4
622
623					-- Handle RTT variance
624					if rtt < 0 then
625						subtree:add(fields.rtt_variance, tvb(offset, 4), -tvb(offset, 4):int())
626					else
627						subtree:add(fields.rtt_variance, tvb(offset, 4))
628					end
629					offset = offset + 4
630
631					-- Handle Available Buffer Size(pkts)
632					subtree:add(fields.buf_size, tvb(offset, 4)):append_text(" pkts")
633					offset = offset + 4
634
635					-- Handle Packets Receiving Rate(Pkts/sec)
636					subtree:add(fields.pack_rcv_rate, tvb(offset, 4)):append_text(" pkts/sec")
637					offset = offset + 4
638
639					-- Handle Estmated Link Capacity
640					subtree:add(fields.est_link_capacity, tvb(offset, 4)):append_text(" pkts/sec")
641					offset = offset + 4
642
643					-- Handle Receiving Rate(bps)
644					subtree:add(fields.rcv_rate, tvb(offset, 4)):append_text(" bps")
645					offset = offset + 4
646				end,
647				[3] = function()
648					pinfo.cols.info:append(" [NAK(loss Report)]")
649					pack_type_tree:append_text(" [NAK(loss Report)]")
650					pack_type_tree:add(fields.msg_type, tvb(offset, 2))
651					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
652					offset = offset + 4
653
654					-- Handle Additional Info, Timestamp and Destination Socket
655					parse_three_param()
656
657					-- Handle lost packet sequence
658					-- lua does not support changing loop variables within loops, but in the form of closures
659					-- https://blog.csdn.net/Ai102iA/article/details/75371239
660					local start = offset
661					local ending = tvb:len()
662					local lost_list_tree = subtree:add(fields.lost_list_tree, tvb(offset, ending - offset))
663					for start in function()
664							local first_bit = bit.rshift(tvb(start, 1):uint(), 7)
665							if first_bit == 1 then
666								local lost_pack_range_tree = lost_list_tree:add(fields.lost_pack_range_tree, tvb(start, 8))
667								local lost_start = bit.band(tvb(start, 4):uint(), 0x7FFFFFFF)
668								lost_pack_range_tree:append_text(" (" .. lost_start .. " -> " .. tvb(start + 4, 4):uint() .. ")")
669								lost_pack_range_tree:add(fields.lost_start, tvb(start, 4), lost_start)
670								start = start + 4
671								lost_pack_range_tree:add(fields.lost_up_to, tvb(start, 4))
672								start = start + 4
673							else
674								lost_list_tree:add(fields.lost_pack_seq, tvb(start, 4))
675								start = start + 4
676							end
677							return start
678						end
679						do
680							if start == ending then
681								break
682							end
683					end
684				end,
685				[4] = function()
686					pinfo.cols.info:append(" [Congestion Warning]")
687					pack_type_tree:append_text(" [Congestion Warning]")
688					pack_type_tree:add(fields.msg_type, tvb(offset, 2))
689					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
690					offset = offset + 4
691				end,
692				[5] = function()
693					pinfo.cols.info:append(" [Shutdown]")
694					pack_type_tree:append_text(" [Shutdown]")
695					pack_type_tree:add(fields.msg_type, tvb(offset, 2))
696					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
697					offset = offset + 4
698
699					-- Handle Additional Info, Timestamp and Destination Socket
700					parse_three_param()
701				end,
702				[6] = function()
703					pinfo.cols.info:append(" [ACKACK]")
704					pack_type_tree:append_text(" [ACKACK]")
705					pack_type_tree:add(fields.msg_type, tvb(offset, 2))
706					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
707					offset = offset + 4
708
709					-- Handle ACK sequence number
710					subtree:add(fields.ack_num, tvb(offset, 4))
711					offset = offset + 4
712
713					-- Handle Time Stamp
714					subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
715					offset = offset + 4
716
717					-- Handle Destination Socket
718					subtree:add(fields.dst_sock, tvb(offset, 4))
719					offset = offset + 4
720
721					-- Handle Control Information
722					subtree:add(fields.ctl_info, tvb(offset, 4))
723					offset = offset + 4
724				end,
725				[7] = function()
726					pinfo.cols.info:append(" [Drop Request]")
727					pack_type_tree:append_text(" [Drop Request]")
728					pack_type_tree:add(fields.msg_type, tvb(offset, 2)):append_text(" [Drop Request]")
729					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
730					offset = offset + 4
731				end,
732				[8] = function()
733					pinfo.cols.info:append(" [Peer Error]")
734					pack_type_tree:append_text(" [Peer Error]")
735					pack_type_tree:add(fields.msg_type, tvb(offset, 2)):append_text(" [Peer Error]")
736					pack_type_tree:add(fields.reserve, tvb(offset + 2, 2)):append_text(" [Undefined]")
737					offset = offset + 4
738				end
739			}
740			-- Handle based on msg_type
741			local case = switch[msg_type]
742			if case then
743				case()
744			else
745				-- default case
746				subtree:add(fields.msg_type, tvb(offset, 2)):append_text(" [Unknown Message Type]")
747				offset = offset + 4
748			end
749		else
750			-- If type field is '0x7FFF', it means an extended type, Handle Reserve field
751			offset = offset + 2
752			local msg_ext_type = tvb(offset, 2):uint()
753			if msg_ext_type == 0 then
754				pinfo.cols.info:append(" [Message Extension]")
755
756				pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [Message Extension]")
757				offset = offset + 2
758
759				-- Handle Additional Info, Time Stamp and Destination Socket
760				parse_three_param()
761
762				-- Control information: defined by user
763			elseif msg_ext_type == 1 or ext_type == 2 then
764				if msg_ext_type == 1 then
765					pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [SRT Handshake Request]")
766					pinfo.cols.info:append(" [SRT Handshake Request]")
767				elseif msg_ext_type == 2 then
768					pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [SRT Handshake Response]")
769					pinfo.cols.info:append(" [SRT Handshake Response]")
770				end
771				offset = offset + 2
772
773				-- Ignore additional info (this field is not defined in this packet type)
774				subtree:add(fields.additional_info, tvb(offset, 4)):append_text(" [undefined]")
775				offset = offset + 4
776
777				-- Handle Time Stamp
778				subtree:add(fields.time_stamp, tvb(offset, 4)):append_text("μs")
779				offset = offset + 4
780
781				-- Handle Destination Socket
782				subtree:add(fields.dst_sock, tvb(offset, 4))
783				offset = offset + 4
784
785				-- Handle SRT Version field
786				subtree:add(fields.srt_version, tvb(offset, 4))
787				offset = ofssset + 4
788
789				-- Handle SRT Flags
790				local SRT_flags_tree = subtree:add(fields.srt_flags, tvb(offset, 4))
791				SRT_flags_tree:add(fields.srt_opt_tsbpdsnd, tvb(offset, 4))
792				SRT_flags_tree:add(fields.srt_opt_tsbpdrcv, tvb(offset, 4))
793				SRT_flags_tree:add(fields.srt_opt_haicrypt, tvb(offset, 4))
794				SRT_flags_tree:add(fields.srt_opt_tlpktdrop, tvb(offset, 4))
795				SRT_flags_tree:add(fields.srt_opt_nakreport, tvb(offset, 4))
796				SRT_flags_tree:add(fields.srt_opt_rexmitflg, tvb(offset, 4))
797				SRT_flags_tree:add(fields.srt_opt_stream, tvb(offset, 4))
798				offset = offset + 4
799
800				-- Handle TsbPd Resv
801				subtree:add(fields.tsbpb_resv, tvb(offset, 2))
802				offset = offset + 2
803
804				-- Handle TsbPb Delay
805				subtree:add(fields.tsbpb_delay, tvb(offset, 2))
806				offset = offset + 2
807
808				-- Handle Reserved field
809				subtree:add(fields.reserve, tvb(offset, 4))
810				offset = offset + 4
811			elseif msg_ext_type == 3 or msg_ext_type == 4 then
812				if msg_ext_type == 3 then
813					pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [Encryption Keying Material Request]")
814					pinfo.cols.info:append(" [Encryption Keying Material Request]")
815				elseif msg_ext_type == 4 then
816					pack_type_tree:add(fields.msg_ext_type, tvb(offset, 2)):append_text(" [Encryption Keying Material Response]")
817					pinfo.cols.info:append(" [Encryption Keying Material Response]")
818				end
819				offset = offset + 2
820
821				-- Ignore additional info (this field is not defined in this packet type)
822				subtree:add(fields.additional_info, tvb(offset, 4)):append_text(" [undefined]")
823				offset = offset + 4
824
825				-- Handle Timestamp
826				subtree:add(fields.time_stamp, tvb(offset, 4)):append_text("μs")
827				offset = offset + 4
828
829				-- Handle Destination Socket
830				subtree:add(fields.dst_sock, tvb(offset, 4))
831				offset = offset + 4
832
833				-- Handle KmErr
834				if msg_ext_type == 4 then
835					subtree:add(fields.km_err, tvb(offset, 4))
836					offset = offset + 4
837					return
838				end
839
840				-- The encrypted message is not handled
841			end
842		end
843	else
844		-- 0 -> Data Packet
845		pack_type_tree:add(fields.pack_type, tvb(offset, 2))
846		pack_type_tree:append_text(" (Data Packet)")
847		local seq_num = tvb(offset, 4):uint()
848		pinfo.cols.info:append(" (Data Packet)(Seq Num:" .. seq_num .. ")")
849
850		-- The first 4 bytes are the package sequence number
851		subtree:add(fields.seq_num, tvb(offset, 4))
852		offset = offset + 4
853
854		data_flag_info_tree = subtree:add(fields.data_flag_info_tree, tvb(offset, 1))
855		-- Handle FF flag
856		local FF_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0xC0), 6)
857		if FF_state == 0 then
858			data_flag_info_tree:append_text(" [Middle packet]")
859		elseif FF_state == 1 then
860			data_flag_info_tree:append_text(" [Last packet]")
861		elseif FF_state == 2 then
862			data_flag_info_tree:append_text(" [First packet]")
863		else
864			data_flag_info_tree:append_text(" [Single packet]")
865		end
866		data_flag_info_tree:add(fields.FF_state, tvb(offset, 1))
867
868		-- Handle O flag
869		local O_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0x20), 5)
870		if O_state == 0 then
871			data_flag_info_tree:append_text(" [Data delivered unordered]")
872		else
873			data_flag_info_tree:append_text(" [Data delivered in order]")
874		end
875		data_flag_info_tree:add(fields.O_state, tvb(offset, 1))
876
877		-- Handle KK flag
878		local KK_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0x18), 3)
879		if KK_state == 1 then
880			data_flag_info_tree:append_text(" [Encrypted with even key]")
881		elseif KK_state == 2 then
882			data_flag_info_tree:append_text(" [Encrypted with odd key]")
883		end
884		data_flag_info_tree:add(fields.KK_state, tvb(offset, 1))
885
886		-- Handle R flag
887		local R_state = bit.rshift(bit.band(tvb(offset, 1):uint(), 0x04), 2)
888		if R_state == 1 then
889			data_flag_info_tree:append_text(" [Retransmit packet]")
890			pinfo.cols.info:append(" [Retransmit packet]")
891		end
892		data_flag_info_tree:add(fields.R_state, tvb(offset, 1))
893
894		-- Handle message number
895		local msg_num = tvb(offset, 4):uint()
896		msg_num = bit.band(tvb(offset, 4):uint(), 0x03FFFFFF)
897		-- subtree:add(fields.msg_num, bit.band(tvb(offset, 4):uint(), 0x03FFFFFF))
898		subtree:add(fields.msg_num, tvb(offset, 4), msg_num)
899		offset = offset + 4
900
901		-- Handle Timestamp
902		subtree:add(fields.time_stamp, tvb(offset, 4)):append_text(" μs")
903		offset = offset + 4
904
905		-- Handle destination socket
906		subtree:add(fields.dst_sock, tvb(offset, 4))
907		offset = offset + 4
908	end
909end
910
911-- Add the protocol into udp table
912local port = 1935
913
914local function enable_dissector()
915	DissectorTable.get("udp.port"):add(port, srt_dev)
916end
917
918-- Call it now - enabled by default
919enable_dissector()
920
921local function disable_dissector()
922	DissectorTable.get("udp.port"):remove(port, srt_dev)
923end
924
925-- Prefs changed will listen at new port
926function srt_dev.prefs_changed()
927	if port ~= srt_dev.prefs.srt_udp_port then
928		if port ~= 0 then
929			disable_dissector()
930		end
931
932		port = srt_dev.prefs.srt_udp_port
933
934		if port ~= 0 then
935			enable_dissector()
936		end
937	end
938end
939