Fix comment end after SPDX identifier
[metze/wireshark/wip.git] / ui / qt / gsm_map_summary_dialog.cpp
1 /* gsm_map_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 "gsm_map_summary_dialog.h"
15 #include <ui_gsm_map_summary_dialog.h>
16
17 #include "config.h"
18
19 #include <glib.h>
20
21 #include "ui/summary.h"
22
23 #include <epan/packet.h>
24 #include <epan/tap.h>
25 #include <epan/asn1.h>
26 #include <epan/dissectors/packet-gsm_map.h>
27
28 #include "wsutil/utf8_entities.h"
29
30 #include "ui/capture_globals.h"
31 #include "ui/simple_dialog.h"
32
33 #include <ui/qt/utils/qt_ui_utils.h>
34 #include "wireshark_application.h"
35
36 #include <QTextStream>
37
38 /** Gsm map statistic data */
39 typedef struct _gsm_map_stat_t {
40     int                 opr_code[GSM_MAP_MAX_NUM_OPR_CODES];
41     int                 size[GSM_MAP_MAX_NUM_OPR_CODES];
42     int                 opr_code_rr[GSM_MAP_MAX_NUM_OPR_CODES];
43     int                 size_rr[GSM_MAP_MAX_NUM_OPR_CODES];
44 } gsm_map_stat_t;
45
46 gsm_map_stat_t gsm_map_stat;
47
48 GsmMapSummaryDialog::GsmMapSummaryDialog(QWidget &parent, CaptureFile &capture_file) :
49     WiresharkDialog(parent, capture_file),
50     ui(new Ui::GsmMapSummaryDialog)
51 {
52     ui->setupUi(this);
53
54     setWindowSubtitle(tr("GSM MAP Summary"));
55     updateWidgets();
56 }
57
58 GsmMapSummaryDialog::~GsmMapSummaryDialog()
59 {
60     delete ui;
61 }
62
63 // Copied from capture_file_properties_dialog.cpp
64 QString GsmMapSummaryDialog::summaryToHtml()
65 {
66     summary_tally summary;
67     memset(&summary, 0, sizeof(summary_tally));
68
69     QString section_tmpl;
70     QString table_begin, table_end;
71     QString table_row_begin, table_ul_row_begin, table_row_end;
72     QString table_vheader_tmpl;
73     QString table_data_tmpl;
74
75     section_tmpl = "<p><strong>%1</strong></p>\n";
76     table_begin = "<p><table>\n";
77     table_end = "</table></p>\n";
78     table_row_begin = "<tr>\n";
79     table_ul_row_begin = "<tr style=\"border-bottom: 1px solid gray;\">\n";
80     table_row_end = "</tr>\n";
81     table_vheader_tmpl = "<td width=\"50%\">%1:</td>"; // <th align="left"> looked odd
82     table_data_tmpl = "<td>%1</td>";
83
84     if (cap_file_.isValid()) {
85         /* initial computations */
86         summary_fill_in(cap_file_.capFile(), &summary);
87 #ifdef HAVE_LIBPCAP
88         summary_fill_in_capture(cap_file_.capFile(), &global_capture_opts, &summary);
89 #endif
90     }
91
92     QString summary_str;
93     QTextStream out(&summary_str);
94
95     // File Section
96     out << section_tmpl.arg(tr("File"));
97     out << table_begin;
98
99     out << table_row_begin
100         << table_vheader_tmpl.arg(tr("Name"))
101         << table_data_tmpl.arg(summary.filename)
102         << table_row_end;
103
104     out << table_row_begin
105         << table_vheader_tmpl.arg(tr("Length"))
106         << table_data_tmpl.arg(file_size_to_qstring(summary.file_length))
107         << table_row_end;
108
109     QString format_str = wtap_file_type_subtype_string(summary.file_type);
110     if (summary.iscompressed) {
111         format_str.append(tr(" (gzip compressed)"));
112     }
113     out << table_row_begin
114         << table_vheader_tmpl.arg(tr("Format"))
115         << table_data_tmpl.arg(format_str)
116         << table_row_end;
117
118     if (summary.snap != 0) {
119         out << table_row_begin
120             << table_vheader_tmpl.arg(tr("Snapshot length"))
121             << table_data_tmpl.arg(summary.snap)
122             << table_row_end;
123     }
124
125     out << table_end;
126
127     // Data Section
128     out << section_tmpl.arg(tr("Data"));
129     out << table_begin;
130
131     if (summary.packet_count_ts == summary.packet_count &&
132             summary.packet_count >= 1)
133     {
134         // start time
135         out << table_row_begin
136             << table_vheader_tmpl.arg(tr("First packet"))
137             << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.start_time))
138             << table_row_end;
139
140         // stop time
141         out << table_row_begin
142             << table_vheader_tmpl.arg(tr("Last packet"))
143             << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.stop_time))
144             << table_row_end;
145
146         // elapsed seconds (capture duration)
147         if (summary.packet_count_ts > 1)
148         {
149             /* elapsed seconds */
150             QString elapsed_str;
151             unsigned int elapsed_time = (unsigned int)summary.elapsed_time;
152             if (elapsed_time/86400)
153             {
154                 elapsed_str = QString("%1 days ").arg(elapsed_time / 86400);
155             }
156
157             elapsed_str += QString("%1:%2:%3")
158                     .arg(elapsed_time % 86400 / 3600, 2, 10, QChar('0'))
159                     .arg(elapsed_time % 3600 / 60, 2, 10, QChar('0'))
160                     .arg(elapsed_time % 60, 2, 10, QChar('0'));
161             out << table_row_begin
162                 << table_vheader_tmpl.arg(tr("Elapsed"))
163                 << table_data_tmpl.arg(elapsed_str)
164                 << table_row_end;
165         }
166     }
167
168     // count
169     out << table_row_begin
170         << table_vheader_tmpl.arg(tr("Packets"))
171         << table_data_tmpl.arg(summary.packet_count)
172         << table_row_end;
173
174     out << table_end;
175
176     QString n_a = UTF8_EM_DASH;
177     QString invoke_rate_str, result_rate_str, total_rate_str;
178     QString invoke_avg_size_str, result_avg_size_str, total_avg_size_str;
179
180     // Message averages
181     invoke_rate_str = result_rate_str = total_rate_str = n_a;
182     invoke_avg_size_str = result_avg_size_str = total_avg_size_str = n_a;
183
184     double seconds = summary.stop_time - summary.start_time;
185     int invoke_count = 0, invoke_bytes = 0;
186     int result_count = 0, result_bytes = 0;
187
188     for (int i = 0; i < GSM_MAP_MAX_NUM_OPR_CODES; i++) {
189         invoke_count += gsm_map_stat.opr_code[i];
190         invoke_bytes += gsm_map_stat.size[i];
191     }
192
193
194     for (int i = 0; i < GSM_MAP_MAX_NUM_OPR_CODES; i++) {
195         result_count += gsm_map_stat.opr_code_rr[i];
196         result_bytes += gsm_map_stat.size_rr[i];
197     }
198
199     int total_count = invoke_count + result_count;
200     int total_bytes = invoke_bytes + result_bytes;
201
202     /*
203      * We must have no un-time-stamped packets (i.e., the number of
204      * time-stamped packets must be the same as the number of packets),
205      * and at least two time-stamped packets, in order for the elapsed
206      * time to be valid.
207      */
208     if (summary.packet_count_ts > 1 && seconds > 0.0) {
209         /* Total number of invokes per second */
210         invoke_rate_str = QString("%1").arg(invoke_count / seconds, 1, 'f', 1);
211         result_rate_str = QString("%1").arg(result_count / seconds, 1, 'f', 1);
212         total_rate_str = QString("%1").arg((total_count) / seconds, 1, 'f', 1);
213     }
214
215     /* Average message sizes */
216     if (invoke_count > 0) {
217         invoke_avg_size_str = QString("%1").arg((double) invoke_bytes / invoke_count, 1, 'f', 1);
218     }
219     if (result_count > 0) {
220         result_avg_size_str = QString("%1").arg((double) result_bytes / result_count, 1, 'f', 1);
221     }
222     if (total_count > 0) {
223         total_avg_size_str = QString("%1").arg((double) total_bytes / total_count, 1, 'f', 1);
224     }
225
226     // Invoke Section
227     out << section_tmpl.arg(tr("Invokes"));
228     out << table_begin;
229
230     out << table_row_begin
231         << table_vheader_tmpl.arg(tr("Total number of Invokes"))
232         << table_data_tmpl.arg(invoke_count)
233         << table_row_end;
234
235     out << table_row_begin
236         << table_vheader_tmpl.arg(tr("Average number of Invokes per second"))
237         << table_data_tmpl.arg(invoke_rate_str)
238         << table_row_end;
239
240     out << table_row_begin
241         << table_vheader_tmpl.arg(tr("Total number of bytes for Invokes"))
242         << table_data_tmpl.arg(invoke_bytes)
243         << table_row_end;
244
245     out << table_row_begin
246         << table_vheader_tmpl.arg(tr("Average number of bytes per Invoke"))
247         << table_data_tmpl.arg(invoke_avg_size_str)
248         << table_row_end;
249
250     out << table_end;
251
252     // Return Result Section
253     out << section_tmpl.arg(tr("Return Results"));
254     out << table_begin;
255
256     out << table_row_begin
257         << table_vheader_tmpl.arg(tr("Total number of Return Results"))
258         << table_data_tmpl.arg(result_count)
259         << table_row_end;
260
261     out << table_row_begin
262         << table_vheader_tmpl.arg(tr("Average number of Return Results per second"))
263         << table_data_tmpl.arg(result_rate_str)
264         << table_row_end;
265
266     out << table_row_begin
267         << table_vheader_tmpl.arg(tr("Total number of bytes for Return Results"))
268         << table_data_tmpl.arg(result_bytes)
269         << table_row_end;
270
271     out << table_row_begin
272         << table_vheader_tmpl.arg(tr("Average number of bytes per Return Result"))
273         << table_data_tmpl.arg(result_avg_size_str)
274         << table_row_end;
275
276     out << table_end;
277
278     // Total Section
279     out << section_tmpl.arg(tr("Totals"));
280     out << table_begin;
281
282     out << table_row_begin
283         << table_vheader_tmpl.arg(tr("Total number of GSM MAP messages"))
284         << table_data_tmpl.arg(total_count)
285         << table_row_end;
286
287     out << table_row_begin
288         << table_vheader_tmpl.arg(tr("Average number of GSM MAP messages per second"))
289         << table_data_tmpl.arg(total_rate_str)
290         << table_row_end;
291
292     out << table_row_begin
293         << table_vheader_tmpl.arg(tr("Total number of bytes for GSM MAP messages"))
294         << table_data_tmpl.arg(total_bytes)
295         << table_row_end;
296
297     out << table_row_begin
298         << table_vheader_tmpl.arg(tr("Average number of bytes per GSM MAP message"))
299         << table_data_tmpl.arg(total_avg_size_str)
300         << table_row_end;
301
302     out << table_end;
303
304     return summary_str;
305 }
306
307 void GsmMapSummaryDialog::updateWidgets()
308 {
309 //    QPushButton *refresh_bt = ui->buttonBox->button(QDialogButtonBox::Reset);
310 //    QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
311
312 //    if (file_closed_) {
313 //        if (refresh_bt) {
314 //            refresh_bt->setEnabled(false);
315 //        }
316 //        ui->commentsTextEdit->setReadOnly(true);
317 //        if (save_bt) {
318 //            save_bt->setEnabled(false);
319 //        }
320 //        return;
321 //    }
322
323     ui->summaryTextEdit->setHtml(summaryToHtml());
324
325     WiresharkDialog::updateWidgets();
326 }
327
328 extern "C" {
329
330 static void
331 gsm_map_summary_reset(void *tapdata)
332 {
333     gsm_map_stat_t *gm_stat = (gsm_map_stat_t *)tapdata;
334
335     memset(gm_stat, 0, sizeof(gsm_map_stat_t));
336 }
337
338
339 static gboolean
340 gsm_map_summary_packet(void *tapdata, packet_info *, epan_dissect_t *, const void *gmtr_ptr)
341 {
342     gsm_map_stat_t *gm_stat = (gsm_map_stat_t *)tapdata;
343     const gsm_map_tap_rec_t *gm_tap_rec = (const gsm_map_tap_rec_t *)gmtr_ptr;
344
345     if (gm_tap_rec->invoke)
346     {
347         gm_stat->opr_code[gm_tap_rec->opcode]++;
348         gm_stat->size[gm_tap_rec->opcode] += gm_tap_rec->size;
349     }
350     else
351     {
352         gm_stat->opr_code_rr[gm_tap_rec->opcode]++;
353         gm_stat->size_rr[gm_tap_rec->opcode] += gm_tap_rec->size;
354     }
355
356     return(FALSE); /* We have no draw callback */
357 }
358
359 void
360 register_tap_listener_qt_gsm_map_summary(void)
361 {
362     GString     *err_p;
363
364     memset((void *) &gsm_map_stat, 0, sizeof(gsm_map_stat_t));
365
366     err_p =
367     register_tap_listener("gsm_map", &gsm_map_stat, NULL, 0,
368         gsm_map_summary_reset,
369         gsm_map_summary_packet,
370         NULL);
371
372     if (err_p != NULL)
373     {
374         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_p->str);
375         g_string_free(err_p, TRUE);
376
377         exit(1);
378     }
379 }
380
381 } // extern "C"
382
383 /*
384  * Editor modelines
385  *
386  * Local Variables:
387  * c-basic-offset: 4
388  * tab-width: 8
389  * indent-tabs-mode: nil
390  * End:
391  *
392  * ex: set shiftwidth=4 tabstop=8 expandtab:
393  * :indentSize=4:tabSize=8:noTabs=true:
394  */