forked from hongch911/WiresharkPlugin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
rtp_pcma_export.lua
197 lines (170 loc) · 7.1 KB
/
rtp_pcma_export.lua
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
-- Dump RTP PCM payload to raw file
-- Write it to from<sourceIp_sourcePort>to<dstIp_dstPort> file.
-- You can access this feature by menu "Tools"
-- Author: Yang Xing ([email protected])
------------------------------------------------------------------------------------------------
do
local proto_pcm = Proto("pcma", "PCMA")
local fp_payload = ProtoField.bytes("pcma.payload", "Raw")
proto_pcm.fields = {
fp_payload
}
-- Wireshark对每个相关数据包调用该函数
-- tvb:Testy Virtual Buffer报文缓存; pinfo:packet infomarmation报文信息; treeitem:解析树节点
function proto_pcm.dissector(tvb, pinfo, tree)
-- add proto item to tree
local proto_tree = tree:add(proto_pcm, tvb())
proto_tree:append_text(string.format(" (Len: %d)",tvb:len()))
pinfo.columns.protocol = "PCMA"
end
-- register this dissector to specific payload type (specified in preferences windows)
local payload_type_table = DissectorTable.get("rtp.pt")
function proto_pcm.init()
payload_type_table:add(8, proto_pcm)
end
function get_temp_path()
local tmp = nil
if tmp == nil or tmp == '' then
tmp = os.getenv('HOME')
if tmp == nil or tmp == '' then
tmp = os.getenv('USERPROFILE')
if tmp == nil or tmp == '' then
tmp = persconffile_path('temp')
else
tmp = tmp .. "/wireshark_temp"
end
else
tmp = tmp .. "/wireshark_temp"
end
end
return tmp
end
-- 导出数据到文件部分
-- for geting data (the field's value is type of ByteArray)
local f_data = Field.new("pcma")
local filter_string = nil
-- menu action. When you click "Tools" will run this function
local function export_data_to_file()
-- window for showing information
local tw = TextWindow.new("Export File Info Win")
-- add message to information window
function twappend(str)
tw:append(str)
tw:append("\n")
end
-- temp path
local temp_path = get_temp_path()
-- variable for storing rtp stream and dumping parameters
local stream_infos = nil
-- trigered by all ps packats
local list_filter = ''
if filter_string == nil or filter_string == '' then
list_filter = "pcma"
elseif string.find(filter_string,"pcma")~=nil then
list_filter = filter_string
else
list_filter = "pcma && "..filter_string
end
twappend("Listener filter: " .. list_filter .. "\n")
local my_tap = Listener.new("frame", list_filter)
-- get rtp stream info by src and dst address
function get_stream_info(pinfo)
local key = "from_" .. tostring(pinfo.src) .. "_" .. tostring(pinfo.src_port) .. "_to_" .. tostring(pinfo.dst) .. "_" .. tostring(pinfo.dst_port)
key = key:gsub(":", ".")
local stream_info = stream_infos[key]
if not stream_info then -- if not exists, create one
stream_info = { }
stream_info.filename = key.. ".pcma.raw"
-- stream_info.file = io.open(stream_info.filename, "wb")
if not Dir.exists(temp_path) then
Dir.make(temp_path)
end
stream_info.filepath = temp_path.."/"..stream_info.filename
stream_info.file,msg = io.open(temp_path.."/"..stream_info.filename, "wb")
if msg then
twappend("io.open "..stream_info.filepath..", error "..msg)
end
stream_infos[key] = stream_info
twappend("Ready to export data (RTP from " .. tostring(pinfo.src) .. ":" .. tostring(pinfo.src_port)
.. " to " .. tostring(pinfo.dst) .. ":" .. tostring(pinfo.dst_port) .. " write to file:[" .. stream_info.filename .. "] ...\n")
end
return stream_info
end
-- write data to file.
local function write_to_file(stream_info, data_bytes)
stream_info.file:write(data_bytes:raw())
end
-- call this function if a packet contains ps payload
function my_tap.packet(pinfo,tvb)
if stream_infos == nil then
-- not triggered by button event, so do nothing.
return
end
local datas = { f_data() } -- using table because one packet may contains more than one RTP
for i,data_f in ipairs(datas) do
if data_f.len < 1 then
return
end
local data = data_f.range:bytes()
local stream_info = get_stream_info(pinfo)
write_to_file(stream_info, data)
end
end
-- close all open files
local function close_all_files()
if stream_infos then
local no_streams = true
for id,stream in pairs(stream_infos) do
if stream and stream.file then
stream.file:flush()
stream.file:close()
stream.file = nil
twappend("File [" .. stream.filename .. "] generated OK!")
twappend("ffplay -ar 8000 -ac 1 -f s16le -acodec pcm_alaw -autoexit "..stream.filename)
no_streams = false
end
end
if no_streams then
twappend("Not found any Data over RTP streams!")
else
tw:add_button("Browser", function () browser_open_data_file(temp_path) end)
end
end
end
function my_tap.reset()
-- do nothing now
end
tw:set_atclose(function ()
my_tap:remove()
if Dir.exists(temp_path) then
Dir.remove_all(temp_path)
end
end)
local function export_data()
stream_infos = {}
retap_packets()
close_all_files()
stream_infos = nil
end
tw:add_button("Export All", function ()
export_data()
end)
tw:add_button("Set Filter", function ()
tw:close()
dialog_menu()
end)
end
local function dialog_func(str)
filter_string = str
export_data_to_file()
end
function dialog_menu()
new_dialog("Filter Dialog",dialog_func,"Filter")
end
local function dialog_default()
filter_string = get_filter()
export_data_to_file()
end
-- Find this feature in menu "Tools"
register_menu("Audio/Export PCMA", dialog_default, MENU_TOOLS_UNSORTED)
end