1 /* mtp3_summary_dialog.cpp
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 */
13
14 #include "mtp3_summary_dialog.h"
15 #include <ui_mtp3_summary_dialog.h>
16
17 #include "config.h"
18
19 #include <glib.h>
20
21 #include <epan/tap.h>
22
23 #include <epan/dissectors/packet-mtp3.h>
24
25 #include "wsutil/utf8_entities.h"
26
27 #include "ui/capture_globals.h"
28 #include "ui/simple_dialog.h"
29 #include "ui/summary.h"
30
31 #include <ui/qt/utils/qt_ui_utils.h>
32
33 #include <QTextStream>
34
35 typedef struct _mtp3_stat_si_code_t {
36 int num_msus;
37 int size;
38 } mtp3_stat_si_code_t;
39
40 typedef struct _mtp3_stat_t {
41 mtp3_addr_pc_t addr_opc;
42 mtp3_addr_pc_t addr_dpc;
43 mtp3_stat_si_code_t mtp3_si_code[MTP3_NUM_SI_CODE];
44 } mtp3_stat_t;
45
46 #define MTP3_MAX_NUM_OPC_DPC 50
47
48 static mtp3_stat_t mtp3_stat[MTP3_MAX_NUM_OPC_DPC];
49 static size_t mtp3_num_used;
50
Mtp3SummaryDialog(QWidget & parent,CaptureFile & capture_file)51 Mtp3SummaryDialog::Mtp3SummaryDialog(QWidget &parent, CaptureFile &capture_file) :
52 WiresharkDialog(parent, capture_file),
53 ui(new Ui::Mtp3SummaryDialog)
54 {
55 ui->setupUi(this);
56
57 setWindowSubtitle(tr("MTP3 Summary"));
58 updateWidgets();
59 }
60
~Mtp3SummaryDialog()61 Mtp3SummaryDialog::~Mtp3SummaryDialog()
62 {
63 delete ui;
64 }
65
summaryToHtml()66 QString Mtp3SummaryDialog::summaryToHtml()
67 {
68 summary_tally summary;
69 memset(&summary, 0, sizeof(summary_tally));
70
71 QString section_tmpl;
72 QString table_begin, table_end;
73 QString table_row_begin, table_ul_row_begin, table_row_end;
74 QString table_vheader_tmpl, table_hheader15_tmpl, table_hheader25_tmpl;
75 QString table_data_tmpl;
76
77 section_tmpl = "<p><strong>%1</strong></p>\n";
78 table_begin = "<p><table>\n";
79 table_end = "</table></p>\n";
80 table_row_begin = "<tr>\n";
81 table_ul_row_begin = "<tr style=\"border-bottom: 1px solid gray;\">\n";
82 table_row_end = "</tr>\n";
83 table_vheader_tmpl = "<td width=\"50%\">%1:</td>"; // <th align="left"> looked odd
84 table_hheader15_tmpl = "<td width=\"15%\"><u>%1</u></td>";
85 table_hheader25_tmpl = "<td width=\"25%\"><u>%1</u></td>";
86 table_data_tmpl = "<td>%1</td>";
87
88 if (cap_file_.isValid()) {
89 /* initial computations */
90 summary_fill_in(cap_file_.capFile(), &summary);
91 #ifdef HAVE_LIBPCAP
92 summary_fill_in_capture(cap_file_.capFile(), &global_capture_opts, &summary);
93 #endif
94 }
95
96 QString summary_str;
97 QTextStream out(&summary_str);
98
99 // File Section
100 out << section_tmpl.arg(tr("File"));
101 out << table_begin;
102
103 out << table_row_begin
104 << table_vheader_tmpl.arg(tr("Name"))
105 << table_data_tmpl.arg(summary.filename)
106 << table_row_end;
107
108 out << table_row_begin
109 << table_vheader_tmpl.arg(tr("Length"))
110 << table_data_tmpl.arg(file_size_to_qstring(summary.file_length))
111 << table_row_end;
112
113 QString format_str = wtap_file_type_subtype_description(summary.file_type);
114 const char *compression_type_description = wtap_compression_type_description(summary.compression_type);
115 if (compression_type_description != NULL) {
116 format_str += QString(" (%1)").arg(compression_type_description);
117 }
118 out << table_row_begin
119 << table_vheader_tmpl.arg(tr("Format"))
120 << table_data_tmpl.arg(format_str)
121 << table_row_end;
122
123 if (summary.snap != 0) {
124 out << table_row_begin
125 << table_vheader_tmpl.arg(tr("Snapshot length"))
126 << table_data_tmpl.arg(summary.snap)
127 << table_row_end;
128 }
129
130 out << table_end;
131
132 // Data Section
133 out << section_tmpl.arg(tr("Data"));
134 out << table_begin;
135
136 if (summary.packet_count_ts == summary.packet_count &&
137 summary.packet_count >= 1)
138 {
139 // start time
140 out << table_row_begin
141 << table_vheader_tmpl.arg(tr("First packet"))
142 << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.start_time))
143 << table_row_end;
144
145 // stop time
146 out << table_row_begin
147 << table_vheader_tmpl.arg(tr("Last packet"))
148 << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.stop_time))
149 << table_row_end;
150
151 // elapsed seconds (capture duration)
152 if (summary.packet_count_ts > 1)
153 {
154 /* elapsed seconds */
155 QString elapsed_str;
156 unsigned int elapsed_time = (unsigned int)summary.elapsed_time;
157 if (elapsed_time/86400)
158 {
159 elapsed_str = QString("%1 days ").arg(elapsed_time / 86400);
160 }
161
162 elapsed_str += QString("%1:%2:%3")
163 .arg(elapsed_time % 86400 / 3600, 2, 10, QChar('0'))
164 .arg(elapsed_time % 3600 / 60, 2, 10, QChar('0'))
165 .arg(elapsed_time % 60, 2, 10, QChar('0'));
166 out << table_row_begin
167 << table_vheader_tmpl.arg(tr("Elapsed"))
168 << table_data_tmpl.arg(elapsed_str)
169 << table_row_end;
170 }
171 }
172
173 // count
174 out << table_row_begin
175 << table_vheader_tmpl.arg(tr("Packets"))
176 << table_data_tmpl.arg(summary.packet_count)
177 << table_row_end;
178
179 out << table_end;
180
181 QString n_a = UTF8_EM_DASH;
182 int total_msus = 0;
183 int total_bytes = 0;
184 double seconds = summary.stop_time - summary.start_time;
185
186 // SI Section
187 out << section_tmpl.arg(tr("Service Indicator (SI) Totals"));
188 out << table_begin;
189
190 out << table_row_begin
191 << table_hheader25_tmpl.arg(tr("SI"))
192 << table_hheader15_tmpl.arg(tr("MSUs"))
193 << table_hheader15_tmpl.arg(tr("MSUs/s"))
194 << table_hheader15_tmpl.arg(tr("Bytes"))
195 << table_hheader15_tmpl.arg(tr("Bytes/MSU"))
196 << table_hheader15_tmpl.arg(tr("Bytes/s"))
197 << table_row_end;
198
199 for (size_t ws_si_code = 0; ws_si_code < MTP3_NUM_SI_CODE; ws_si_code++) {
200 int si_msus = 0;
201 int si_bytes = 0;
202 QString msus_s_str = n_a;
203 QString bytes_msu_str = n_a;
204 QString bytes_s_str = n_a;
205
206 for (size_t stat_idx = 0; stat_idx < mtp3_num_used; stat_idx++) {
207 si_msus += mtp3_stat[stat_idx].mtp3_si_code[ws_si_code].num_msus;
208 si_bytes += mtp3_stat[stat_idx].mtp3_si_code[ws_si_code].size;
209 }
210 total_msus += si_msus;
211 total_bytes += si_bytes;
212
213 if (seconds > 0) {
214 msus_s_str = QString("%1").arg(si_msus / seconds, 1, 'f', 1);
215 bytes_s_str = QString("%1").arg(si_bytes / seconds, 1, 'f', 1);
216 }
217
218 if (si_msus > 0) {
219 bytes_msu_str = QString("%1").arg((double) si_bytes / si_msus, 1, 'f', 1);
220 }
221
222 out << table_row_begin
223 << table_data_tmpl.arg(mtp3_service_indicator_code_short_vals[ws_si_code].strptr)
224 << table_data_tmpl.arg(si_msus)
225 << table_data_tmpl.arg(msus_s_str)
226 << table_data_tmpl.arg(si_bytes)
227 << table_data_tmpl.arg(bytes_msu_str)
228 << table_data_tmpl.arg(bytes_s_str)
229 << table_row_end;
230 }
231
232 out << table_end;
233
234 // Totals Section
235
236 QString total_msus_s_str = n_a;
237 QString total_bytes_msu_str = n_a;
238 QString total_bytes_s_str = n_a;
239
240 if (seconds > 0) {
241 total_msus_s_str = QString("%1").arg(total_msus / seconds, 1, 'f', 1);
242 total_bytes_s_str = QString("%1").arg(total_bytes / seconds, 1, 'f', 1);
243 }
244 if (total_msus > 0) {
245 total_bytes_msu_str = QString("%1").arg((double) total_bytes / total_msus, 1, 'f', 1);
246 }
247
248 out << section_tmpl.arg(tr("Totals"));
249 out << table_begin;
250
251 out << table_row_begin
252 << table_vheader_tmpl.arg(tr("Total MSUs"))
253 << table_data_tmpl.arg(total_msus)
254 << table_row_end;
255
256 out << table_row_begin
257 << table_vheader_tmpl.arg(tr("MSUs/s"))
258 << table_data_tmpl.arg(total_msus_s_str)
259 << table_row_end;
260
261 out << table_row_begin
262 << table_vheader_tmpl.arg(tr("Total Bytes"))
263 << table_data_tmpl.arg(total_bytes)
264 << table_row_end;
265
266 out << table_row_begin
267 << table_vheader_tmpl.arg(tr("Average Bytes/MSU"))
268 << table_data_tmpl.arg(total_bytes_msu_str)
269 << table_row_end;
270
271 out << table_row_begin
272 << table_vheader_tmpl.arg(tr("Average Bytes/s"))
273 << table_data_tmpl.arg(total_bytes_s_str)
274 << table_row_end;
275
276 out << table_end;
277
278 return summary_str;
279 }
280
updateWidgets()281 void Mtp3SummaryDialog::updateWidgets()
282 {
283 ui->summaryTextEdit->setHtml(summaryToHtml());
284
285 WiresharkDialog::updateWidgets();
286 }
287
288 extern "C" {
289
290 void register_tap_listener_qt_mtp3_summary(void);
291
292 static void
mtp3_summary_reset(void * tapdata)293 mtp3_summary_reset(
294 void *tapdata)
295 {
296 mtp3_stat_t (*stat_p)[MTP3_MAX_NUM_OPC_DPC] = (mtp3_stat_t(*)[MTP3_MAX_NUM_OPC_DPC])tapdata;
297
298 mtp3_num_used = 0;
299 memset(stat_p, 0, MTP3_MAX_NUM_OPC_DPC * sizeof(mtp3_stat_t));
300 }
301
302
303 static tap_packet_status
mtp3_summary_packet(void * tapdata,packet_info *,epan_dissect_t *,const void * data)304 mtp3_summary_packet(
305 void *tapdata,
306 packet_info *,
307 epan_dissect_t *,
308 const void *data)
309 {
310 mtp3_stat_t (*stat_p)[MTP3_MAX_NUM_OPC_DPC] = (mtp3_stat_t(*)[MTP3_MAX_NUM_OPC_DPC])tapdata;
311 const mtp3_tap_rec_t *data_p = (const mtp3_tap_rec_t *)data;
312 size_t i;
313
314 if (data_p->mtp3_si_code >= MTP3_NUM_SI_CODE)
315 {
316 /*
317 * we thought this si_code was not used ?
318 * is MTP3_NUM_SI_CODE out of date ?
319 * XXX - if this is an error, report it and return TAP_PACKET_FAILED.
320 */
321 return(TAP_PACKET_DONT_REDRAW);
322 }
323
324 /*
325 * look for opc/dpc pair
326 */
327 i = 0;
328 while (i < mtp3_num_used)
329 {
330 if (memcmp(&data_p->addr_opc, &(*stat_p)[i].addr_opc, sizeof(mtp3_addr_pc_t)) == 0)
331 {
332 if (memcmp(&data_p->addr_dpc, &(*stat_p)[i].addr_dpc, sizeof(mtp3_addr_pc_t)) == 0)
333 {
334 break;
335 }
336 }
337
338 i++;
339 }
340
341 if (i == mtp3_num_used)
342 {
343 if (mtp3_num_used == MTP3_MAX_NUM_OPC_DPC)
344 {
345 /*
346 * too many
347 * XXX - report an error and return TAP_PACKET_FAILED?
348 */
349 return(TAP_PACKET_DONT_REDRAW);
350 }
351
352 mtp3_num_used++;
353 }
354
355 (*stat_p)[i].addr_opc = data_p->addr_opc;
356 (*stat_p)[i].addr_dpc = data_p->addr_dpc;
357 (*stat_p)[i].mtp3_si_code[data_p->mtp3_si_code].num_msus++;
358 (*stat_p)[i].mtp3_si_code[data_p->mtp3_si_code].size += data_p->size;
359
360 return(TAP_PACKET_REDRAW);
361 }
362
363 void
register_tap_listener_qt_mtp3_summary(void)364 register_tap_listener_qt_mtp3_summary(void)
365 {
366 GString *err_p;
367
368 memset((void *) &mtp3_stat, 0, sizeof(mtp3_stat));
369
370 err_p =
371 register_tap_listener("mtp3", &mtp3_stat, NULL, 0,
372 mtp3_summary_reset,
373 mtp3_summary_packet,
374 NULL,
375 NULL);
376
377 if (err_p != NULL)
378 {
379 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_p->str);
380 g_string_free(err_p, TRUE);
381
382 exit(1);
383 }
384 }
385
386 } // extern "C"
387