Fix comment end after SPDX identifier
[metze/wireshark/wip.git] / ui / qt / mtp3_summary_dialog.cpp
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
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
61 Mtp3SummaryDialog::~Mtp3SummaryDialog()
62 {
63     delete ui;
64 }
65
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_string(summary.file_type);
114     if (summary.iscompressed) {
115         format_str.append(tr(" (gzip compressed)"));
116     }
117     out << table_row_begin
118         << table_vheader_tmpl.arg(tr("Format"))
119         << table_data_tmpl.arg(format_str)
120         << table_row_end;
121
122     if (summary.snap != 0) {
123         out << table_row_begin
124             << table_vheader_tmpl.arg(tr("Snapshot length"))
125             << table_data_tmpl.arg(summary.snap)
126             << table_row_end;
127     }
128
129     out << table_end;
130
131     // Data Section
132     out << section_tmpl.arg(tr("Data"));
133     out << table_begin;
134
135     if (summary.packet_count_ts == summary.packet_count &&
136             summary.packet_count >= 1)
137     {
138         // start time
139         out << table_row_begin
140             << table_vheader_tmpl.arg(tr("First packet"))
141             << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.start_time))
142             << table_row_end;
143
144         // stop time
145         out << table_row_begin
146             << table_vheader_tmpl.arg(tr("Last packet"))
147             << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.stop_time))
148             << table_row_end;
149
150         // elapsed seconds (capture duration)
151         if (summary.packet_count_ts > 1)
152         {
153             /* elapsed seconds */
154             QString elapsed_str;
155             unsigned int elapsed_time = (unsigned int)summary.elapsed_time;
156             if (elapsed_time/86400)
157             {
158                 elapsed_str = QString("%1 days ").arg(elapsed_time / 86400);
159             }
160
161             elapsed_str += QString("%1:%2:%3")
162                     .arg(elapsed_time % 86400 / 3600, 2, 10, QChar('0'))
163                     .arg(elapsed_time % 3600 / 60, 2, 10, QChar('0'))
164                     .arg(elapsed_time % 60, 2, 10, QChar('0'));
165             out << table_row_begin
166                 << table_vheader_tmpl.arg(tr("Elapsed"))
167                 << table_data_tmpl.arg(elapsed_str)
168                 << table_row_end;
169         }
170     }
171
172     // count
173     out << table_row_begin
174         << table_vheader_tmpl.arg(tr("Packets"))
175         << table_data_tmpl.arg(summary.packet_count)
176         << table_row_end;
177
178     out << table_end;
179
180     QString n_a = UTF8_EM_DASH;
181     int total_msus = 0;
182     int total_bytes = 0;
183     double seconds = summary.stop_time - summary.start_time;
184
185     // SI Section
186     out << section_tmpl.arg(tr("Service Indicator (SI) Totals"));
187     out << table_begin;
188
189     out << table_row_begin
190         << table_hheader25_tmpl.arg(tr("SI"))
191         << table_hheader15_tmpl.arg(tr("MSUs"))
192         << table_hheader15_tmpl.arg(tr("MSUs/s"))
193         << table_hheader15_tmpl.arg(tr("Bytes"))
194         << table_hheader15_tmpl.arg(tr("Bytes/MSU"))
195         << table_hheader15_tmpl.arg(tr("Bytes/s"))
196         << table_row_end;
197
198     for (size_t ws_si_code = 0; ws_si_code < MTP3_NUM_SI_CODE; ws_si_code++) {
199         int si_msus = 0;
200         int si_bytes = 0;
201         QString msus_s_str = n_a;
202         QString bytes_msu_str = n_a;
203         QString bytes_s_str = n_a;
204
205         for (size_t stat_idx = 0; stat_idx < mtp3_num_used; stat_idx++) {
206             si_msus += mtp3_stat[stat_idx].mtp3_si_code[ws_si_code].num_msus;
207             si_bytes += mtp3_stat[stat_idx].mtp3_si_code[ws_si_code].size;
208         }
209         total_msus += si_msus;
210         total_bytes += si_bytes;
211
212         if (seconds > 0) {
213             msus_s_str = QString("%1").arg(si_msus / seconds, 1, 'f', 1);
214             bytes_s_str = QString("%1").arg(si_bytes / seconds, 1, 'f', 1);
215         }
216
217         if (si_msus > 0) {
218             bytes_msu_str = QString("%1").arg((double) si_bytes / si_msus, 1, 'f', 1);
219         }
220
221         out << table_row_begin
222             << table_data_tmpl.arg(mtp3_service_indicator_code_short_vals[ws_si_code].strptr)
223             << table_data_tmpl.arg(si_msus)
224             << table_data_tmpl.arg(msus_s_str)
225             << table_data_tmpl.arg(si_bytes)
226             << table_data_tmpl.arg(bytes_msu_str)
227             << table_data_tmpl.arg(bytes_s_str)
228             << table_row_end;
229     }
230
231     out << table_end;
232
233     // Totals Section
234
235     QString total_msus_s_str = n_a;
236     QString total_bytes_msu_str = n_a;
237     QString total_bytes_s_str = n_a;
238
239     if (seconds > 0) {
240         total_msus_s_str = QString("%1").arg(total_msus / seconds, 1, 'f', 1);
241         total_bytes_s_str = QString("%1").arg(total_bytes / seconds, 1, 'f', 1);
242     }
243     if (total_msus > 0) {
244         total_bytes_msu_str = QString("%1").arg((double) total_bytes / total_msus, 1, 'f', 1);
245     }
246
247     out << section_tmpl.arg(tr("Totals"));
248     out << table_begin;
249
250     out << table_row_begin
251         << table_vheader_tmpl.arg(tr("Total MSUs"))
252         << table_data_tmpl.arg(total_msus)
253         << table_row_end;
254
255     out << table_row_begin
256         << table_vheader_tmpl.arg(tr("MSUs/s"))
257         << table_data_tmpl.arg(total_msus_s_str)
258         << table_row_end;
259
260     out << table_row_begin
261         << table_vheader_tmpl.arg(tr("Total Bytes"))
262         << table_data_tmpl.arg(total_bytes)
263         << table_row_end;
264
265     out << table_row_begin
266         << table_vheader_tmpl.arg(tr("Average Bytes/MSU"))
267         << table_data_tmpl.arg(total_bytes_msu_str)
268         << table_row_end;
269
270     out << table_row_begin
271         << table_vheader_tmpl.arg(tr("Average Bytes/s"))
272         << table_data_tmpl.arg(total_bytes_s_str)
273         << table_row_end;
274
275     out << table_end;
276
277     return summary_str;
278 }
279
280 void Mtp3SummaryDialog::updateWidgets()
281 {
282     ui->summaryTextEdit->setHtml(summaryToHtml());
283
284     WiresharkDialog::updateWidgets();
285 }
286
287 extern "C" {
288
289 static void
290 mtp3_summary_reset(
291     void        *tapdata)
292 {
293     mtp3_stat_t     (*stat_p)[MTP3_MAX_NUM_OPC_DPC] = (mtp3_stat_t(*)[MTP3_MAX_NUM_OPC_DPC])tapdata;
294
295     mtp3_num_used = 0;
296     memset(stat_p, 0, MTP3_MAX_NUM_OPC_DPC * sizeof(mtp3_stat_t));
297 }
298
299
300 static gboolean
301 mtp3_summary_packet(
302     void            *tapdata,
303     packet_info     *,
304     epan_dissect_t  *,
305     const void      *data)
306 {
307     mtp3_stat_t           (*stat_p)[MTP3_MAX_NUM_OPC_DPC] = (mtp3_stat_t(*)[MTP3_MAX_NUM_OPC_DPC])tapdata;
308     const mtp3_tap_rec_t  *data_p = (const mtp3_tap_rec_t *)data;
309     size_t                 i;
310
311     if (data_p->mtp3_si_code >= MTP3_NUM_SI_CODE)
312     {
313         /*
314          * we thought this si_code was not used ?
315          * is MTP3_NUM_SI_CODE out of date ?
316          */
317         return(FALSE);
318     }
319
320     /*
321      * look for opc/dpc pair
322      */
323     i = 0;
324     while (i < mtp3_num_used)
325     {
326         if (memcmp(&data_p->addr_opc, &(*stat_p)[i].addr_opc, sizeof(mtp3_addr_pc_t)) == 0)
327         {
328             if (memcmp(&data_p->addr_dpc, &(*stat_p)[i].addr_dpc, sizeof(mtp3_addr_pc_t)) == 0)
329             {
330                 break;
331             }
332         }
333
334         i++;
335     }
336
337     if (i == mtp3_num_used)
338     {
339         if (mtp3_num_used == MTP3_MAX_NUM_OPC_DPC)
340         {
341             /*
342              * too many
343              */
344             return(FALSE);
345         }
346
347         mtp3_num_used++;
348     }
349
350     (*stat_p)[i].addr_opc = data_p->addr_opc;
351     (*stat_p)[i].addr_dpc = data_p->addr_dpc;
352     (*stat_p)[i].mtp3_si_code[data_p->mtp3_si_code].num_msus++;
353     (*stat_p)[i].mtp3_si_code[data_p->mtp3_si_code].size += data_p->size;
354
355     return(TRUE);
356 }
357
358 void
359 register_tap_listener_qt_mtp3_summary(void)
360 {
361     GString     *err_p;
362
363     memset((void *) &mtp3_stat, 0, sizeof(mtp3_stat));
364
365     err_p =
366     register_tap_listener("mtp3", &mtp3_stat, NULL, 0,
367         mtp3_summary_reset,
368         mtp3_summary_packet,
369         NULL);
370
371     if (err_p != NULL)
372     {
373         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_p->str);
374         g_string_free(err_p, TRUE);
375
376         exit(1);
377     }
378 }
379
380 } // extern "C"
381
382 /*
383  * Editor modelines
384  *
385  * Local Variables:
386  * c-basic-offset: 4
387  * tab-width: 8
388  * indent-tabs-mode: nil
389  * End:
390  *
391  * ex: set shiftwidth=4 tabstop=8 expandtab:
392  * :indentSize=4:tabSize=8:noTabs=true:
393  */