1 /* service_response_time_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "service_response_time_dialog.h"
28 #include <ui/service_response_time.h>
30 #include "rpc_service_response_time_dialog.h"
31 #include "wireshark_application.h"
33 #include <QMessageBox>
34 #include <QTreeWidget>
35 #include <QTreeWidgetItemIterator>
37 static QHash<const QString, register_srt_t *> cfg_str_to_srt_;
41 srt_init(const char *args, void*) {
42 QStringList args_l = QString(args).split(',');
43 if (args_l.length() > 1) {
44 QString srt = QString("%1,%2").arg(args_l[0]).arg(args_l[1]);
46 if (args_l.length() > 2) {
47 filter = QStringList(args_l.mid(2)).join(",");
49 wsApp->emitTapParameterSignal(srt, filter, NULL);
54 void register_service_response_tables(gpointer data, gpointer)
56 register_srt_t *srt = (register_srt_t*)data;
57 const char* short_name = proto_get_protocol_short_name(find_protocol_by_id(get_srt_proto_id(srt)));
58 const char *cfg_abbr = srt_table_get_tap_string(srt);
59 tpdCreator tpd_creator = ServiceResponseTimeDialog::createSrtDialog;
61 /* XXX - These dissectors haven't been converted over to due to an "interactive input dialog" for their
62 tap data. Let those specific dialogs register for themselves */
63 if (strcmp(short_name, "DCERPC") == 0) {
64 short_name = "DCE-RPC";
65 tpd_creator = RpcServiceResponseTimeDialog::createDceRpcSrtDialog;
66 } else if (strcmp(short_name, "RPC") == 0) {
67 short_name = "ONC-RPC";
68 tpd_creator = RpcServiceResponseTimeDialog::createOncRpcSrtDialog;
71 cfg_str_to_srt_[cfg_abbr] = srt;
72 TapParameterDialog::registerDialog(
75 REGISTER_STAT_GROUP_RESPONSE_TIME,
81 srt_table_type_ = 1000,
85 class SrtRowTreeWidgetItem : public QTreeWidgetItem
88 SrtRowTreeWidgetItem(QTreeWidgetItem *parent, const srt_procedure_t *procedure) :
89 QTreeWidgetItem (parent, srt_row_type_),
92 setText(SRT_COLUMN_PROCEDURE, procedure_->procedure);
97 setText(SRT_COLUMN_INDEX, QString::number(procedure_->index));
98 setText(SRT_COLUMN_CALLS, QString::number(procedure_->stats.num));
99 setText(SRT_COLUMN_MIN, QString::number(nstime_to_sec(&procedure_->stats.min), 'f', 6));
100 setText(SRT_COLUMN_MAX, QString::number(nstime_to_sec(&procedure_->stats.max), 'f', 6));
101 setText(SRT_COLUMN_AVG, QString::number(get_average(&procedure_->stats.tot, procedure_->stats.num) / 1000.0, 'f', 6));
102 setText(SRT_COLUMN_SUM, QString::number(nstime_to_sec(&procedure_->stats.tot), 'f', 6));
104 for (int col = 0; col < columnCount(); col++) {
105 if (col == SRT_COLUMN_PROCEDURE) continue;
106 setTextAlignment(col, Qt::AlignRight);
109 setHidden(procedure_->stats.num < 1);
112 bool operator< (const QTreeWidgetItem &other) const
114 if (other.type() != srt_row_type_) return QTreeWidgetItem::operator< (other);
115 const SrtRowTreeWidgetItem *other_row = static_cast<const SrtRowTreeWidgetItem *>(&other);
117 switch (treeWidget()->sortColumn()) {
118 case SRT_COLUMN_INDEX:
119 return procedure_->index < other_row->procedure_->index;
120 case SRT_COLUMN_CALLS:
121 return procedure_->stats.num < other_row->procedure_->stats.num;
123 return nstime_cmp(&procedure_->stats.min, &other_row->procedure_->stats.min) < 0;
125 return nstime_cmp(&procedure_->stats.max, &other_row->procedure_->stats.max) < 0;
128 double our_avg = get_average(&procedure_->stats.tot, procedure_->stats.num);
129 double other_avg = get_average(&other_row->procedure_->stats.tot, other_row->procedure_->stats.num);
130 return our_avg < other_avg;
133 return nstime_cmp(&procedure_->stats.tot, &other_row->procedure_->stats.tot) < 0;
138 return QTreeWidgetItem::operator< (other);
140 QList<QVariant> rowData() {
141 return QList<QVariant>() << QString(procedure_->procedure) << procedure_->index << procedure_->stats.num
142 << nstime_to_sec(&procedure_->stats.min) << nstime_to_sec(&procedure_->stats.max)
143 << get_average(&procedure_->stats.tot, procedure_->stats.num) / 1000.0
144 << nstime_to_sec(&procedure_->stats.tot);
147 const srt_procedure_t *procedure_;
150 class SrtTableTreeWidgetItem : public QTreeWidgetItem
153 SrtTableTreeWidgetItem(QTreeWidget *parent, const srt_stat_table *srt_table) :
154 QTreeWidgetItem (parent, srt_table_type_),
155 srt_table_(srt_table)
157 setText(0, srt_table_->name);
158 setFirstColumnSpanned(true);
161 for (int i = 0; i < srt_table_->num_procs; i++) {
162 new SrtRowTreeWidgetItem(this, &srt_table_->procedures[i]);
165 const QString columnTitle() { return srt_table_->proc_column_name; }
167 QList<QVariant> rowData() {
168 return QList<QVariant>() << srt_table_->name;
170 const QString filterField() { return srt_table_->filter_string; }
173 const srt_stat_table *srt_table_;
177 ServiceResponseTimeDialog::ServiceResponseTimeDialog(QWidget &parent, CaptureFile &cf, register_srt *srt, const QString filter, int help_topic) :
178 TapParameterDialog(parent, cf, help_topic),
181 QString subtitle = QString("%1 Service Response Time Statistics")
182 .arg(proto_get_protocol_short_name(find_protocol_by_id(get_srt_proto_id(srt))));
183 setWindowSubtitle(subtitle);
185 // Add number of columns for this stats_tree
186 QStringList header_labels;
187 for (int col = 0; col < NUM_SRT_COLUMNS; col++) {
188 header_labels.push_back(service_response_time_get_column_name(col));
190 statsTreeWidget()->setColumnCount(header_labels.count());
191 statsTreeWidget()->setHeaderLabels(header_labels);
193 for (int col = 0; col < statsTreeWidget()->columnCount(); col++) {
194 if (col == SRT_COLUMN_PROCEDURE) continue;
195 statsTreeWidget()->headerItem()->setTextAlignment(col, Qt::AlignRight);
200 if (!filter.isEmpty()) {
201 setDisplayFilter(filter);
204 connect(statsTreeWidget(), SIGNAL(itemChanged(QTreeWidgetItem*,int)),
205 this, SLOT(statsTreeWidgetItemChanged()));
208 TapParameterDialog *ServiceResponseTimeDialog::createSrtDialog(QWidget &parent, const QString cfg_str, const QString filter, CaptureFile &cf)
210 if (!cfg_str_to_srt_.contains(cfg_str)) {
215 register_srt_t *srt = cfg_str_to_srt_[cfg_str];
217 return new ServiceResponseTimeDialog(parent, cf, srt, filter);
220 void ServiceResponseTimeDialog::addSrtTable(const struct _srt_stat_table *srt_table)
222 new SrtTableTreeWidgetItem(statsTreeWidget(), srt_table);
225 void ServiceResponseTimeDialog::tapReset(void *srtd_ptr)
227 srt_data_t *srtd = (srt_data_t*) srtd_ptr;
228 ServiceResponseTimeDialog *srt_dlg = static_cast<ServiceResponseTimeDialog *>(srtd->user_data);
229 if (!srt_dlg) return;
231 reset_srt_table(srtd->srt_array, NULL, NULL);
233 srt_dlg->statsTreeWidget()->clear();
234 for (guint i = 0; i < srtd->srt_array->len; i++) {
235 srt_stat_table *srt_table = g_array_index(srtd->srt_array, srt_stat_table*, i);
236 srt_dlg->addSrtTable(srt_table);
240 void ServiceResponseTimeDialog::tapDraw(void *srtd_ptr)
242 srt_data_t *srtd = (srt_data_t*) srtd_ptr;
243 ServiceResponseTimeDialog *srt_dlg = static_cast<ServiceResponseTimeDialog *>(srtd->user_data);
244 if (!srt_dlg || !srt_dlg->statsTreeWidget()) return;
246 QTreeWidgetItemIterator it(srt_dlg->statsTreeWidget());
248 if ((*it)->type() == srt_row_type_) {
249 SrtRowTreeWidgetItem *srtr_ti = static_cast<SrtRowTreeWidgetItem *>((*it));
255 for (int i = 0; i < srt_dlg->statsTreeWidget()->columnCount() - 1; i++) {
256 srt_dlg->statsTreeWidget()->resizeColumnToContents(i);
260 void ServiceResponseTimeDialog::fillTree()
263 srt_data.srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table*));
264 srt_data.user_data = this;
266 srt_table_dissector_init(srt_, srt_data.srt_array, NULL, NULL);
268 QString display_filter = displayFilter();
269 GString *error_string = register_tap_listener(get_srt_tap_listener_name(srt_),
271 display_filter.toUtf8().constData(),
274 get_srt_packet_func(srt_),
277 QMessageBox::critical(this, tr("Failed to attach to tap \"%1\"").arg(get_srt_tap_listener_name(srt_)),
279 g_string_free(error_string, TRUE);
280 g_array_free(srt_data.srt_array, TRUE);
284 statsTreeWidget()->setSortingEnabled(false);
286 cap_file_.retapPackets();
288 // We only have one table. Move its tree items up one level.
289 if (statsTreeWidget()->invisibleRootItem()->childCount() == 1) {
290 statsTreeWidget()->setRootIndex(statsTreeWidget()->model()->index(0, 0));
295 statsTreeWidget()->sortItems(SRT_COLUMN_PROCEDURE, Qt::AscendingOrder);
296 statsTreeWidget()->setSortingEnabled(true);
298 remove_tap_listener(&srt_data);
299 g_array_free(srt_data.srt_array, TRUE);
302 QList<QVariant> ServiceResponseTimeDialog::treeItemData(QTreeWidgetItem *ti) const
305 if (ti->type() == srt_table_type_) {
306 SrtTableTreeWidgetItem *srtt_ti = static_cast<SrtTableTreeWidgetItem *>(ti);
308 tid << srtt_ti->rowData();
310 } else if (ti->type() == srt_row_type_) {
311 SrtRowTreeWidgetItem *srtr_ti = static_cast<SrtRowTreeWidgetItem *>(ti);
313 tid << srtr_ti->rowData();
319 const QString ServiceResponseTimeDialog::filterExpression()
322 if (statsTreeWidget()->selectedItems().count() > 0) {
323 QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0];
324 if (ti->type() == srt_row_type_) {
325 SrtTableTreeWidgetItem *srtt_ti = static_cast<SrtTableTreeWidgetItem *>(ti->parent());
326 QString field = srtt_ti->filterField();
327 QString value = ti->text(SRT_COLUMN_INDEX);
328 if (srtt_ti && !field.isEmpty() && !value.isEmpty()) {
329 filter_expr = QString("%1==%2").arg(srtt_ti->filterField()).arg(value);
336 void ServiceResponseTimeDialog::statsTreeWidgetItemChanged()
338 QString procedure_title = service_response_time_get_column_name(SRT_COLUMN_PROCEDURE);
340 if (statsTreeWidget()->selectedItems().count() > 0) {
341 QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0];
342 SrtTableTreeWidgetItem *srtt_ti = NULL;
343 if (ti->type() == srt_row_type_) {
344 srtt_ti = static_cast<SrtTableTreeWidgetItem *>(ti->parent());
346 srtt_ti = static_cast<SrtTableTreeWidgetItem *>(ti);
349 procedure_title = srtt_ti->columnTitle();
352 statsTreeWidget()->headerItem()->setText(SRT_COLUMN_PROCEDURE, procedure_title);
361 * indent-tabs-mode: nil
364 * ex: set shiftwidth=4 tabstop=8 expandtab:
365 * :indentSize=4:tabSize=8:noTabs=true: