您的位置:首页 > 编程语言 > Lua

wireshark lua: Dissector for RTP dynamic payload type(如何编写RTP Payload解析器)

2010-09-12 17:37 513 查看
本文介绍如何用wireshark lua编写解析RTP Payload的解析器(dissector)。查看wireshark RTP解析器源码可知,RTP里有三个解析器table:

1. "rtp.pt" ——用于指定payload type值注册解析器,一般payload type小于96的标准解析器已经预先注册到该table;
2. "rtp_dyn_payload_type"——用于注册解析dynamic payload(type>=96)的解析器,注册时必须指定动态payload type的字符串名称,该名称与SDP里的rtpmap里的媒体类型(media type)名称对应,比如a=rtpmap:96 H264/9000中的H264。
3. "rtp_hdr_ext"——应该用于解析自定义rtp扩展头(没研究过该table怎么用)。

无论是用C还是lua语言写解析器,都可以注册到"rtp.pt"或"rtp_dyn_payload_type"两个table里,以解析RTP Payload内容。

通常需要自己写解析器的一般都是自定义格式的RTP Payload,payload type通常大于等于96。可能第一个想到的是解析器以媒体类型名称注册到"rtp_dyn_payload_type" table上就够了,但实际上动态payload type需要倚仗其它会话协议解析器(如SIP/RTSP)和SDP解析器的正确解析后,才能正确的调用"rtp_dyn_payload_type" table里根据名称注册的解析器。但实际上现在的wireshark(我用的1.2.7版本)有时会话协议解析结果(比如RTSP)不能正确调用我们注册到"rtp_dyn_payload_type" table里的解析器,所以有必要把payload解析器也注册到rtp.pt table上。(wireshark自带的H264解析协议就是个例子)

以下是一个解析RTP动态payload的lua dissector例子:

-- Dissector for rtp payload (demo)
-- Author: Huang Qiangxiong (qiangxiong.huang@gmail.com)
-- change log:
--      2010-09-12
--          Just can play
------------------------------------------------------------------------------------------------
do
local my_rtp_payload_proto = Proto("my_rtp_payload_test", "RTP Payload Test [HQX's plugins]: test")

local prefs = my_rtp_payload_proto.prefs
prefs.dyn_pt = Pref.uint("MY_RTP_PAYLOAD_TEST dynamic payload type", 0, "The value > 95")

---- my dissector for rtp payload
function my_rtp_payload_proto.dissector(tvb, pinfo, tree)
-- add proto item to tree
local subtree = tree:add(my_rtp_payload_proto, tvb())
subtree:append_text("MY_RTP_PAYLOAD_TEST")
-- ... other dissector code ...
end

-- register this dissector to dynamic payload type dissectorTable
local dyn_payload_type_table = DissectorTable.get("rtp_dyn_payload_type")
dyn_payload_type_table:add("MYRTP", my_rtp_payload_proto)

-- register this dissector to specific payload type (specified in preferences windows)
local payload_type_table = DissectorTable.get("rtp.pt")
local old_dissector = nil
local old_dyn_pt = 0
function my_rtp_payload_proto.init()
if (prefs.dyn_pt ~= old_dyn_pt) then
if (old_dyn_pt > 0) then -- reset old dissector
if (old_dissector == nil) then -- just remove this proto
payload_type_table:remove(old_dyn_pt, my_rtp_payload_proto)
else  -- replace this proto with old proto on old payload type
payload_type_table:add(old_dyn_pt, old_dissector)
end
end
old_dyn_pt = prefs.dyn_pt  -- save current payload type's dissector
old_dissector = payload_type_table:get_dissector(old_dyn_pt)
if (prefs.dyn_pt > 0) then
payload_type_table:add(prefs.dyn_pt, my_rtp_payload_proto)
end
end
end
end


代码默认把解析器以MYRTP为媒体类型名称,注册到动态payload type解析器列表"rtp_dyn_payload_type" table上。

然后为该协议设置了一个配置项,允许用户指定RTP的dynamic payload type值为多少时用本协议解析器解析。该配置默认值为0,表示不指定payload type解析,用户需要修改时,可到菜单Edit->Preferences打开窗口中,选择Protocols->MY_RTP_PAYLOAD_TEST协议配置窗口里修改该配置项(显示名为:MY_RTP_PAYLOAD_TEST dynamic payload type)。

代码中init()函数的作用是,每次启动wireshark或修改协议配置项时都会调用该函数,本处该函数主要的职责是根据配置的payload type,把解析器注册到"rtp.pt" table的对应payload type上,另外,还要处理用户修改配置指定新的payload type后,恢复原payload type的解析器(原payload type未指定解析器,则把本解析器从原payload type上删除)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: