-- 1. declare a new type of protocol
local rtpp = Proto("rtpp", "RTP over RTSP(iPanel Flavor)")
-- 2. define some field into the rtpp
local pf_rtpp_magic = ProtoField.uint8("rtpp.magic", "Magic", base.HEX)
local pf_rtpp_channel = ProtoField.uint8("rtpp.channel", "Interleaved Channel", base.HEX)
local pf_rtpp_length = ProtoField.uint16("rtpp.length", "Length")
-- data 就是⽆法识别净荷内容的情况下简单的将其设置为⼆进制数据的⽅法
local default_parser = Dissector.get("data")
-- 3. 注册新协议拥有的字段, 这些字段可作为以后抽取数据之⽤
rtpp.fields = {
pf_rtpp_magic,
pf_rtpp_channel,
pf_rtpp_length,
}
-- 前向声明
local dissect_rtpp
local rtpp_min_len = 4
-- 此处处理TCP 重传的逻辑
function rtpp.dissector(tvbuf, pktinfo, root)
local segment_length = tvbuf:len()
local bytes_consumed = 0
local reported_len = tvbuf:reported_length_remaining()
if segment_length ~= reported_len then
-- captured packets are being sliced/cut-off,
-- so don't try to desegment/reassemble
return 0
end
while bytes_consumed < segment_length do
-- 此处会调⽤具体的解析函数
local result = dissect_rtpp(tvbuf, pktinfo, root, bytes_consumed)
if result == 0 then
return 0
elseif result > 0 then
bytes_consumed = bytes_consumed + result
else
tinfo.desegment_offset = bytes_consumed
result = -result
pktinfo.desegment_len = result
return segment_length
end
end
return bytes_consumed
end
-- RTP over RTSP 有基本的RTSP 协议信令也有数据流,
-- 对基本的信令⽤默认的RTSP 解析器来解析
-- 对interleaved-channel 形式的按照其载荷类型来解析
dissect_rtpp = function(tvbuf, pinfo, root, offset)
local msglen = tvbuf:len() - offset
debug("sub_buf len=" .. msglen .. ", offset=" .. offset)
if msglen < rtpp_min_len then
debug("sliced packet")
return - DESEGMENT_ONE_MORE_SEGMENT
end
-- 分类解析
if tvbuf:range(offset, 1):uint() ~= 0x24 then
-- 以普通的rtsp 消息来解析
debug("interpret packet as normal rtsp")
local rtsp_dissector = Dissector.get("rtsp")
-- 此处的返回值尚不清楚, 对此的处理也⽐较幼稚
rtsp_dissector:call(tvbuf:range(offset, msglen):tvb(), pinfo, root)
info("ret=" .. ret)
return msglen
else
-- interleaved-channel 形式
debug("interpret packet as interleaved channel")
local len_buf = tvbuf:range(offset + 2, 2)
local payload_len = len_buf:uint()
local packet_len = payload_len + 4
debug("rtsp packet_len=" .. packet_len .. ", payload_len load=" .. pyload_len)
-- ⾄少需要4 个字节才可以区分出该包是否属于RTP over RTSP 协议
if msglen < packet_len then
return -(packet_len - msglen)
end
-- 添加⼀些界⾯显⽰信息
root:add(pf_rtpp_magic, tvbuf:range(offset + 0, 1))
root:add(pf_rtpp_channel, tvbuf:range(offset + 1, 1))
root:add(pf_rtpp_length, len_buf)
offset = offset + 4
-- 取净荷的第⼀个字节来区分mpeg 和rtp
local probe_byte = tvbuf:range(offset, 1):uint()
debug("probe_byte=" .. string.format( "0x%x ", probe_byte))
if probe_byte == 0x47 then
-- 0x47 开头的就⽤mpeg 的解析器来解析
debug("raw mp2t packet, offset=" .. offset .. ", payload_len=" .. payload_len)
local mpeg_dissector = Dissector.get("mp2t")
while (offset + 188) <= packet_len do
local mpeg_tvb = tvbuf:range(offset, packet_len - offset):tvb()
-- 暂时不知道该函数的返回值是什么情况
mpeg_dissector:call(mpeg_tvb, pinfo, root)
offset = offset + 188
end
return offset
elseif probe_byte == 0x80 then
-- 0x80 开头的尝试⽤rtp 来解析
debug("RTP packet, offset=" .. offset .. ", payload_len=" .. payload_len)
local rtp_dissector = Dissector.get("rtp")
local rtp_tvb = tvbuf:range(offset, payload_len):tvb()
-- 同样也是对返回值的情况不太了解.
rtp_dissector:call(rtp_tvb, pinfo, root)
if msglen ~= packet_len then
debug("length not match, payload_len + 4=" .. packet_len.. ", msglen=" .. msglen)
end
return packet_len
else
default_parser(tvbuf, pinfo, root)
return packet_len
end
end
end
-- 将RTP over RTSP 协议注册到554 端⼝
-- 需要注意的是因为调⽤了原⽣RTSP 解析器, 所以我们的解析结果并不影响普通的rtsp 解析
tcp_dissector_table:add(554, rtpp)
tcp_dissector_table:add(2554, rtpp)
info("rtpp (RTP over RTSP) protocol registed at TCP port 554")