aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-08-12 14:09:35 -0700
committerGerald Combs <gerald@wireshark.org>2015-08-18 20:17:20 +0000
commit0e8cc9ab0ad41d09cbc886d1283266aea989c563 (patch)
tree4baceddfc9d74c8754dce9226f82678bf4a050ae
parent9a3d4e6eef9851f7368c89364add3759919b8f95 (diff)
UDP multicast stream dialog.
Add the UDP multicast stream dialog. Abuse TapParameterDialog a bit more so that we can edit parameters. Remove some unused struct members and an unused function. Change-Id: I962c70344e792f0959527e4bcba8a20bd7e8acf9 Reviewed-on: https://code.wireshark.org/review/10084 Petri-Dish: Gerald Combs <gerald@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
-rw-r--r--doc/wireshark.pod.template4
-rw-r--r--ui/cli/tap-rtp.c2
-rw-r--r--ui/gtk/mcast_stream_dlg.c18
-rw-r--r--ui/gtk/rtp_stream_dlg.c2
-rw-r--r--ui/mcast_stream.c27
-rw-r--r--ui/mcast_stream.h14
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/Makefile.common2
-rw-r--r--ui/qt/Wireshark.pro2
-rw-r--r--ui/qt/main_window.h2
-rw-r--r--ui/qt/main_window.ui9
-rw-r--r--ui/qt/main_window_slots.cpp14
-rw-r--r--ui/qt/multicast_statistics_dialog.cpp491
-rw-r--r--ui/qt/multicast_statistics_dialog.h72
-rw-r--r--ui/qt/response_time_delay_dialog.cpp20
-rw-r--r--ui/qt/service_response_time_dialog.cpp44
-rw-r--r--ui/qt/tap_parameter_dialog.cpp62
-rw-r--r--ui/qt/tap_parameter_dialog.h13
-rw-r--r--ui/qt/tap_parameter_dialog.ui3
-rw-r--r--ui/rtp_stream.h1
-rw-r--r--ui/tap-rtp-common.c2
-rw-r--r--wsutil/str_util.c1
22 files changed, 713 insertions, 94 deletions
diff --git a/doc/wireshark.pod.template b/doc/wireshark.pod.template
index 55fcf7260c..f414d4bf90 100644
--- a/doc/wireshark.pod.template
+++ b/doc/wireshark.pod.template
@@ -836,6 +836,10 @@ on those calls that match that filter.
Example: B<-z "mgcp,srt,ip.addr==1.2.3.4"> will collect stats only for
MGCP packets exchanged by the host at IP address 1.2.3.4 .
+=item B<-z> multicast,stat[,<filter>]
+
+Show UDP multicast stream statistics.
+
=item B<-z> rpc,programs
Collect call/reply SRT data for all known ONC-RPC programs/versions.
diff --git a/ui/cli/tap-rtp.c b/ui/cli/tap-rtp.c
index 0b9635f26b..eee1f13e9e 100644
--- a/ui/cli/tap-rtp.c
+++ b/ui/cli/tap-rtp.c
@@ -51,7 +51,7 @@ void register_tap_listener_rtp_streams(void);
/* The one and only global rtpstream_tapinfo_t structure for tshark and wireshark.
*/
static rtpstream_tapinfo_t the_tapinfo_struct =
- {NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, 0, FALSE};
+ {NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE};
static void
rtp_streams_stat_draw(void *arg _U_)
diff --git a/ui/gtk/mcast_stream_dlg.c b/ui/gtk/mcast_stream_dlg.c
index 716a4eb305..faba11c867 100644
--- a/ui/gtk/mcast_stream_dlg.c
+++ b/ui/gtk/mcast_stream_dlg.c
@@ -50,13 +50,11 @@
static void mcaststream_dlg_update(void *ti_ptr);
-void register_tap_listener_mcast_stream_dlg(void);
-
/****************************************************************************/
/* the one and only global mcaststream_tapinfo_t structure for tshark and wireshark.
*/
static mcaststream_tapinfo_t the_tapinfo_struct =
- {mcaststream_dlg_update, 0, NULL, 0, NULL, 0, FALSE};
+ {NULL, NULL, mcaststream_dlg_update, NULL, 0, NULL, FALSE};
/* Capture callback data keys */
#define E_MCAST_ENTRY_1 "burst_interval"
@@ -397,9 +395,9 @@ add_to_list_store(mcast_stream_info_t* strinfo)
data[2] = g_strdup(dst_addr);
data[3] = g_strdup_printf("%u", strinfo->dest_port);
data[4] = g_strdup_printf("%u", strinfo->npackets);
- data[5] = g_strdup_printf("%u /s", strinfo->apackets);
- data[6] = g_strdup_printf("%2.1f Mbps", strinfo->average_bw);
- data[7] = g_strdup_printf("%2.1f Mbps", strinfo->element.maxbw);
+ data[5] = g_strdup_printf("%.1f /s", strinfo->apackets);
+ data[6] = g_strdup_printf("%2.1f Mbps", strinfo->average_bw/1000000);
+ data[7] = g_strdup_printf("%2.1f Mbps", strinfo->element.maxbw/1000000);
data[8] = g_strdup_printf("%u / %dms", strinfo->element.topburstsize, mcast_stream_burstint);
data[9] = g_strdup_printf("%u", strinfo->element.numbursts);
data[10] = g_strdup_printf("%.1f KB", (float)strinfo->element.topbuffusage/1000);
@@ -438,7 +436,7 @@ add_to_list_store(mcast_stream_info_t* strinfo)
g_snprintf(label_text, sizeof(label_text),
"Detected %d Multicast streams, Average Bw: %.1f Mbps Max Bw: %.1f Mbps Max burst: %d / %dms Max buffer: %.1f KB",
++streams_nb,
- mcaststream_dlg_get_tapinfo()->allstreams->average_bw, mcaststream_dlg_get_tapinfo()->allstreams->element.maxbw,
+ mcaststream_dlg_get_tapinfo()->allstreams->average_bw/1000000, mcaststream_dlg_get_tapinfo()->allstreams->element.maxbw/1000000,
mcaststream_dlg_get_tapinfo()->allstreams->element.topburstsize, mcast_stream_burstint,
(float)(mcaststream_dlg_get_tapinfo()->allstreams->element.topbuffusage)/1000);
gtk_label_set_text(GTK_LABEL(top_label), label_text);
@@ -826,12 +824,6 @@ mcaststream_launch(GtkAction *action _U_, gpointer user_data _U_)
/* Tap listener will be removed and cleaned up in mcaststream_on_destroy */
}
-/****************************************************************************/
-void
-register_tap_listener_mcast_stream_dlg(void)
-{
-}
-
mcaststream_tapinfo_t *mcaststream_dlg_get_tapinfo(void) {
return &the_tapinfo_struct;
}
diff --git a/ui/gtk/rtp_stream_dlg.c b/ui/gtk/rtp_stream_dlg.c
index 1762f7e6d2..8916eed598 100644
--- a/ui/gtk/rtp_stream_dlg.c
+++ b/ui/gtk/rtp_stream_dlg.c
@@ -59,7 +59,7 @@ void register_tap_listener_rtp_stream_dlg(void);
*/
static rtpstream_tapinfo_t the_tapinfo_struct =
{ rtpstream_tap_draw, rtpstream_dlg_mark_packet, NULL, 0, NULL, 0,
- TAP_ANALYSE, NULL, NULL, NULL, 0, FALSE
+ TAP_ANALYSE, NULL, NULL, NULL, FALSE
};
/****************************************************************************/
diff --git a/ui/mcast_stream.c b/ui/mcast_stream.c
index 6a845a384b..0a0790038f 100644
--- a/ui/mcast_stream.c
+++ b/ui/mcast_stream.c
@@ -110,18 +110,19 @@ mcaststream_reset(mcaststream_tapinfo_t *tapinfo)
g_free(tapinfo->allstreams);
tapinfo->allstreams = NULL;
- tapinfo->nstreams = 0;
tapinfo->npackets = 0;
- ++(tapinfo->launch_count);
-
return;
}
static void
-mcaststream_reset_cb(void *arg)
+mcaststream_reset_cb(void *ti_ptr)
{
- mcaststream_reset((mcaststream_tapinfo_t *)arg);
+ mcaststream_tapinfo_t *tapinfo = (mcaststream_tapinfo_t *)ti_ptr;
+ if (tapinfo && tapinfo->tap_reset) {
+ tapinfo->tap_reset(ti_ptr);
+ }
+ mcaststream_reset(tapinfo);
}
/****************************************************************************/
@@ -143,7 +144,7 @@ mcaststream_draw(void *ti_ptr)
/****************************************************************************/
/* whenever a udp packet is seen by the tap listener */
-static int
+static gboolean
mcaststream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2 _U_)
{
mcaststream_tapinfo_t *tapinfo = (mcaststream_tapinfo_t *)arg;
@@ -256,12 +257,16 @@ mcaststream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const
/* calculate average bandwidth for this stream */
strinfo->total_bytes = strinfo->total_bytes + pinfo->fd->pkt_len;
- if (deltatime > 0)
- strinfo->average_bw = (((double)(strinfo->total_bytes*8) / deltatime) / 1000000);
/* increment the packets counter for this stream and calculate average pps */
++(strinfo->npackets);
- strinfo->apackets = (guint32) (strinfo->npackets / deltatime);
+
+ if (deltatime > 0) {
+ strinfo->apackets = strinfo->npackets / deltatime;
+ strinfo->average_bw = ((double)(strinfo->total_bytes*8) / deltatime);
+ } else {
+ strinfo->apackets = strinfo->average_bw = 0.0;
+ }
/* time between first and last packet in any group */
tapinfo->allstreams->stop_rel = pinfo->rel_ts;
@@ -274,7 +279,7 @@ mcaststream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const
/* calculate average bandwidth for all streams */
tapinfo->allstreams->total_bytes = tapinfo->allstreams->total_bytes + pinfo->fd->pkt_len;
if (deltatime > 0)
- tapinfo->allstreams->average_bw = (((double)(tapinfo->allstreams->total_bytes *8) / deltatime) / 1000000);
+ tapinfo->allstreams->average_bw = ((double)(tapinfo->allstreams->total_bytes*8) / deltatime);
/* sliding window and buffercalc for this group*/
slidingwindow(strinfo, pinfo);
@@ -439,7 +444,7 @@ slidingwindow(mcast_stream_info_t *strinfo, packet_info *pinfo)
strinfo->element.burstsize = diff;
if(strinfo->element.burstsize > strinfo->element.topburstsize) {
strinfo->element.topburstsize = strinfo->element.burstsize;
- strinfo->element.maxbw = (double)(strinfo->element.topburstsize) * 1000 / mcast_stream_burstint * pinfo->fd->pkt_len * 8 / 1000000;
+ strinfo->element.maxbw = (double)(strinfo->element.topburstsize) * 1000 / mcast_stream_burstint * pinfo->fd->pkt_len * 8;
}
strinfo->element.last++;
diff --git a/ui/mcast_stream.h b/ui/mcast_stream.h
index f3417aee73..e780f8e885 100644
--- a/ui/mcast_stream.h
+++ b/ui/mcast_stream.h
@@ -52,7 +52,7 @@ typedef struct buffer{
gint32 buffstatus; /* buffer status */
gint32 numbuffalarms; /* number of alarms triggered by buffer underruns */
gint32 topbuffusage; /* top buffer usage in refresh interval */
- double maxbw; /* maximum bandwidth usage */
+ double maxbw; /* Maximum bandwidth usage. Bits/s */
} t_buffer;
@@ -63,9 +63,9 @@ typedef struct _mcast_stream_info {
address dest_addr;
guint16 dest_port;
guint32 npackets;
- guint32 apackets;
+ double apackets;
guint32 total_bytes;
- double average_bw;
+ double average_bw; /* Bits/s */
guint32 first_frame_num; /* frame number of first frame */
/* start of recording (GMT) of this stream */
@@ -83,13 +83,13 @@ typedef struct _mcast_stream_info {
/* structure that holds the information about all detected streams */
/* struct holding all information of the tap */
typedef struct _mcaststream_tapinfo {
- tap_draw_cb tap_draw; /**< tap draw callback */
- int nstreams; /* number of streams in the list */
- GList* strinfo_list; /* list with all streams */
+ gpointer user_data; /* User data pointer */
+ tap_reset_cb tap_reset; /**< tap reset callback */
+ tap_draw_cb tap_draw; /**< tap draw callback */
+ GList* strinfo_list; /* list of mcast_stream_info_t */
guint32 npackets; /* total number of mcast packets of all streams */
mcast_stream_info_t* allstreams; /* structure holding information common for all streams */
- guint32 launch_count; /* number of times the tap has been run */
gboolean is_registered; /* if the tap listener is currently registered or not */
} mcaststream_tapinfo_t;
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 370a18261b..b43922fedb 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -84,6 +84,7 @@ set(WIRESHARK_QT_HEADERS
main_window_preferences_frame.h
manage_interfaces_dialog.h
module_preferences_scroll_area.h
+ multicast_statistics_dialog.h
overlay_scroll_bar.h
packet_comment_dialog.h
packet_dialog.h
@@ -286,6 +287,7 @@ set(WIRESHARK_QT_TAP_SRC
funnel_statistics.cpp
gsm_map_summary_dialog.cpp
io_graph_dialog.cpp
+ multicast_statistics_dialog.cpp
rtp_stream_dialog.cpp
sctp_all_assocs_dialog.cpp
sctp_assoc_analyse_dialog.cpp
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index 87a5fa735c..142b511444 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -198,6 +198,7 @@ MOC_HDRS = \
main_window_preferences_frame.h \
manage_interfaces_dialog.h \
module_preferences_scroll_area.h \
+ multicast_statistics_dialog.h \
overlay_scroll_bar.h \
packet_comment_dialog.h \
packet_dialog.h \
@@ -490,6 +491,7 @@ WIRESHARK_QT_TAP_SRC = \
funnel_statistics.cpp \
gsm_map_summary_dialog.cpp \
io_graph_dialog.cpp \
+ multicast_statistics_dialog.cpp \
rtp_stream_dialog.cpp \
sctp_all_assocs_dialog.cpp \
sctp_assoc_analyse_dialog.cpp \
diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro
index 46d313d873..627a66e8e4 100644
--- a/ui/qt/Wireshark.pro
+++ b/ui/qt/Wireshark.pro
@@ -324,6 +324,7 @@ HEADERS += $$HEADERS_WS_C \
main_window_preferences_frame.h \
manage_interfaces_dialog.h \
module_preferences_scroll_area.h \
+ multicast_statistics_dialog.h \
overlay_scroll_bar.h \
packet_comment_dialog.h \
packet_dialog.h \
@@ -708,6 +709,7 @@ SOURCES += \
main_window_slots.cpp \
manage_interfaces_dialog.cpp \
module_preferences_scroll_area.cpp \
+ multicast_statistics_dialog.cpp \
overlay_scroll_bar.cpp \
packet_comment_dialog.cpp \
packet_dialog.cpp \
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 49e9a90cde..ad17ef355d 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -477,6 +477,8 @@ private slots:
void on_actionSCTPShowAllAssociations_triggered();
void on_actionSCTPAnalyseThisAssociation_triggered();
void on_actionSCTPFilterThisAssociation_triggered();
+ void statCommandMulticastStatistics(const char *arg, void *);
+ void on_actionStatisticsUdpMulticastStreams_triggered();
void openStatisticsTreeDialog(const gchar *abbr);
void on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered();
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 7a0e8ec493..f3f621c799 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -492,6 +492,7 @@
<addaction name="actionStatisticsHTTP2"/>
<addaction name="actionStatisticsSametime"/>
<addaction name="menuTcpStreamGraphs"/>
+ <addaction name="actionStatisticsUdpMulticastStreams"/>
</widget>
<widget class="QMenu" name="menuTelephony">
<property name="title">
@@ -2637,6 +2638,14 @@
<string>Go to the packet referenced by the selected field.</string>
</property>
</action>
+ <action name="actionStatisticsUdpMulticastStreams">
+ <property name="text">
+ <string>UDP Multicast Streams</string>
+ </property>
+ <property name="toolTip">
+ <string>Show UTP multicast stream statistics.</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index 9663744b16..a98a84cba9 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -127,6 +127,7 @@
#include "tap_parameter_dialog.h"
#include "tcp_stream_dialog.h"
#include "time_shift_dialog.h"
+#include "multicast_statistics_dialog.h"
#include "voip_calls_dialog.h"
#include "wireshark_application.h"
#include "filter_action.h"
@@ -2635,6 +2636,19 @@ void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered()
openTcpStreamDialog(GRAPH_WSCALE);
}
+void MainWindow::statCommandMulticastStatistics(const char *arg, void *)
+{
+ MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg);
+ connect(mcast_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
+ this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+ mcast_stats_dlg->show();
+}
+
+void MainWindow::on_actionStatisticsUdpMulticastStreams_triggered()
+{
+ statCommandMulticastStatistics(NULL, NULL);
+}
+
void MainWindow::openStatisticsTreeDialog(const gchar *abbr)
{
StatsTreeDialog *st_dialog = new StatsTreeDialog(*this, capture_file_, abbr);
diff --git a/ui/qt/multicast_statistics_dialog.cpp b/ui/qt/multicast_statistics_dialog.cpp
new file mode 100644
index 0000000000..4b4da27446
--- /dev/null
+++ b/ui/qt/multicast_statistics_dialog.cpp
@@ -0,0 +1,491 @@
+/* multicast_statistics_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "multicast_statistics_dialog.h"
+
+#include "ui/mcast_stream.h"
+
+#include <QFormLayout>
+#include <QLabel>
+#include <QPushButton>
+#include <QTreeWidget>
+
+#include "qt_ui_utils.h"
+#include "syntax_line_edit.h"
+#include "wireshark_application.h"
+
+enum {
+ col_src_addr_,
+ col_src_port_,
+ col_dst_addr_,
+ col_dst_port_,
+ col_packets_,
+ col_packets_s_,
+ col_avg_bw_,
+ col_max_bw_,
+ col_max_burst_,
+ col_burst_alarms_,
+ col_max_buffers_,
+ col_buffer_alarms_
+};
+
+enum {
+ mcast_table_type_ = 1000
+};
+
+class MulticastStatTreeWidgetItem : public QTreeWidgetItem
+{
+public:
+ MulticastStatTreeWidgetItem(QTreeWidget *parent) :
+ QTreeWidgetItem (parent, mcast_table_type_)
+ {
+ memset(&src_addr_, 0, sizeof(src_addr_));
+ memset(&dst_addr_, 0, sizeof(dst_addr_));
+ }
+
+ void updateStreamInfo(const mcast_stream_info_t *stream_info) {
+ copy_address(&src_addr_, &stream_info->src_addr);
+ src_port_ = stream_info->src_port;
+ copy_address(&dst_addr_, &stream_info->dest_addr);
+ dst_port_ = stream_info->dest_port;
+ num_packets_ = stream_info->npackets;
+ avg_pps_ = stream_info->apackets;
+ avg_bw_ = stream_info->average_bw;
+ max_bw_ = stream_info->element.maxbw;
+ top_burst_size_ = stream_info->element.topburstsize;
+ num_bursts_ = stream_info->element.numbursts;
+ top_buff_usage_ = stream_info->element.topbuffusage;
+ num_buff_alarms_ = stream_info->element.numbuffalarms;
+
+ draw();
+ }
+
+ void draw() {
+ setText(col_src_addr_, address_to_qstring(&src_addr_));
+ setText(col_src_port_, QString::number(src_port_));
+ setText(col_dst_addr_, address_to_qstring(&dst_addr_));
+ setText(col_dst_port_, QString::number(dst_port_));
+ setText(col_packets_, QString::number(num_packets_));
+ setText(col_packets_s_, QString::number(avg_pps_, 'f', 2));
+ setText(col_avg_bw_, bits_s_to_qstring(avg_bw_));
+ setText(col_max_bw_, bits_s_to_qstring(max_bw_));
+ setText(col_max_burst_, QString("%1 / %2ms").arg(top_burst_size_).arg(mcast_stream_burstint));
+ setText(col_burst_alarms_, QString::number(num_bursts_));
+ setText(col_max_buffers_, bits_s_to_qstring(top_buff_usage_));
+ setText(col_buffer_alarms_, QString::number(num_buff_alarms_));
+ }
+
+ bool operator< (const QTreeWidgetItem &other) const
+ {
+ if (other.type() != mcast_table_type_) return QTreeWidgetItem::operator< (other);
+ const MulticastStatTreeWidgetItem *other_row = static_cast<const MulticastStatTreeWidgetItem *>(&other);
+
+ switch (treeWidget()->sortColumn()) {
+ case col_src_addr_:
+ return cmp_address(&src_addr_, &other_row->src_addr_) < 0;
+ case col_src_port_:
+ return src_port_ < other_row->src_port_;
+ case col_dst_addr_:
+ return cmp_address(&dst_addr_, &other_row->dst_addr_) < 0;
+ case col_dst_port_:
+ return dst_port_ < other_row->dst_port_;
+ case col_packets_:
+ return num_packets_ < other_row->num_packets_;
+ case col_packets_s_:
+ return avg_pps_ < other_row->avg_pps_;
+ case col_avg_bw_:
+ return avg_bw_ < other_row->avg_bw_;
+ case col_max_bw_:
+ return max_bw_ < other_row->max_bw_;
+ case col_max_burst_:
+ return top_burst_size_ < other_row->top_burst_size_;
+ case col_burst_alarms_:
+ return num_bursts_ < other_row->num_bursts_;
+ case col_max_buffers_:
+ return top_buff_usage_ < other_row->top_buff_usage_;
+ case col_buffer_alarms_:
+ return num_buff_alarms_ < other_row->num_buff_alarms_;
+ default:
+ break;
+ }
+
+ return QTreeWidgetItem::operator< (other);
+ }
+ QList<QVariant> rowData() {
+ return QList<QVariant>()
+ << address_to_qstring(&src_addr_) << src_port_
+ << address_to_qstring(&dst_addr_) << dst_port_
+ << num_packets_ << avg_pps_
+ << avg_bw_ << max_bw_
+ << top_burst_size_ << num_bursts_
+ << top_buff_usage_ << num_buff_alarms_;
+ }
+ const QString filterExpression() {
+ QString ip_version;
+
+ if (src_addr_.type == AT_IPv6) ip_version = "v6";
+
+ const QString filter_expr = QString("(ip%1.src==%2 && udp.srcport==%3 && ip%1.dst==%4 && udp.dstport==%5)")
+ .arg(ip_version)
+ .arg(address_to_qstring(&src_addr_))
+ .arg(src_port_)
+ .arg(address_to_qstring(&dst_addr_))
+ .arg(dst_port_);
+ return filter_expr;
+ }
+
+private:
+ address src_addr_;
+ guint16 src_port_;
+ address dst_addr_;
+ guint16 dst_port_;
+ unsigned num_packets_;
+ double avg_pps_;
+ double avg_bw_;
+ double max_bw_;
+ int top_burst_size_;
+ int num_bursts_;
+ int top_buff_usage_;
+ int num_buff_alarms_;
+};
+
+MulticastStatisticsDialog::MulticastStatisticsDialog(QWidget &parent, CaptureFile &cf, const char *filter) :
+ TapParameterDialog(parent, cf)
+{
+ setWindowSubtitle(tr("UDP Multicast Streams"));
+
+ // XXX Use recent settings instead
+ resize(parent.width() * 4 / 5, parent.height() * 3 / 4);
+
+ tapinfo_ = new mcaststream_tapinfo_t();
+ tapinfo_->user_data = this;
+ tapinfo_->tap_reset = tapReset;
+ tapinfo_->tap_draw = tapDraw;
+
+ QStringList header_names = QStringList()
+ << tr("Source Address") << tr("Source Port")
+ << tr("Destination Address") << tr("Destination Port")
+ << tr("Packets") << tr("Packets/s")
+ << tr("Avg BW (bps)") << tr("Max BW (bps)")
+ << tr("Max Burst") << tr("Burst Alarms")
+ << tr("Max Buffers (B)") << tr("Buffer Alarms");
+
+ statsTreeWidget()->setHeaderLabels(header_names);
+
+ for (int col = 0; col < statsTreeWidget()->columnCount(); col++) {
+ if (col == col_src_addr_ || col == col_dst_addr_) continue;
+ statsTreeWidget()->headerItem()->setTextAlignment(col, Qt::AlignRight);
+ }
+
+ burst_measurement_interval_le_ = new SyntaxLineEdit(this);
+ burst_alarm_threshold_le_ = new SyntaxLineEdit(this);
+ buffer_alarm_threshold_le_ = new SyntaxLineEdit(this);
+ stream_empty_speed_le_ = new SyntaxLineEdit(this);
+ total_empty_speed_le_ = new SyntaxLineEdit(this);
+
+ int filter_layout_idx = verticalLayout()->indexOf(filterLayout()->widget());
+ QGridLayout *param_grid = new QGridLayout();
+ int one_em = fontMetrics().height();
+ verticalLayout()->insertLayout(filter_layout_idx, param_grid);
+
+ // Label | LineEdit | | Label | LineEdit | | Label | LineEdit
+ // 0 1 2 3 4 5 6 7
+ param_grid->setColumnMinimumWidth(2, one_em * 2);
+ param_grid->setColumnStretch(2, 1);
+ param_grid->setColumnMinimumWidth(5, one_em * 2);
+ param_grid->setColumnStretch(5, 1);
+ param_grid->addWidget(new QLabel(tr("Burst measurement interval (ms):")), 0, 0, Qt::AlignRight);
+ param_grid->addWidget(burst_measurement_interval_le_, 0, 1);
+ param_grid->addWidget(new QLabel(tr("Burst alarm threshold (packets):")), 0, 3, Qt::AlignRight);
+ param_grid->addWidget(burst_alarm_threshold_le_, 0, 4);
+ param_grid->addWidget(new QLabel(tr("Buffer alarm threshold (B):")), 0, 6, Qt::AlignRight);
+ param_grid->addWidget(buffer_alarm_threshold_le_, 0, 7);
+
+ param_grid->addWidget(new QLabel(tr("Stream empty speed (Kb/s:")), 1, 0, Qt::AlignRight);
+ param_grid->addWidget(stream_empty_speed_le_, 1, 1);
+ param_grid->addWidget(new QLabel(tr("Total empty speed (Kb/s:")), 1, 3, Qt::AlignRight);
+ param_grid->addWidget(total_empty_speed_le_, 1, 4);
+
+ burst_measurement_interval_le_->setText(QString::number(mcast_stream_burstint));
+ burst_alarm_threshold_le_->setText(QString::number(mcast_stream_trigger));
+ buffer_alarm_threshold_le_->setText(QString::number(mcast_stream_bufferalarm));
+ stream_empty_speed_le_->setText(QString::number(mcast_stream_emptyspeed));
+ total_empty_speed_le_->setText(QString::number(mcast_stream_cumulemptyspeed));
+
+ line_edits_ = QList<QWidget *>()
+ << burst_measurement_interval_le_ << burst_alarm_threshold_le_
+ << buffer_alarm_threshold_le_ << stream_empty_speed_le_
+ << total_empty_speed_le_;
+
+ foreach (QWidget *line_edit, line_edits_) {
+ line_edit->setMinimumWidth(one_em * 5);
+ connect(line_edit, SIGNAL(textEdited(QString)), this, SLOT(updateWidgets()));
+ }
+
+ addFilterActions();
+
+ if (filter) {
+ setDisplayFilter(filter);
+ }
+
+ connect(this, SIGNAL(updateFilter(QString&,bool)),
+ this, SLOT(updateMulticastParameters()));
+
+ connect(&cap_file_, SIGNAL(captureFileClosing()),
+ this, SLOT(captureFileClosing()));
+
+ /* Register the tap listener */
+ register_tap_listener_mcast_stream(tapinfo_);
+
+ updateWidgets();
+ QTimer::singleShot(0, this, SLOT(fillTree()));
+}
+
+MulticastStatisticsDialog::~MulticastStatisticsDialog()
+{
+ /* Remove the stream tap listener */
+ remove_tap_listener_mcast_stream(tapinfo_);
+
+ /* Clean up memory used by stream tap */
+ mcaststream_reset(tapinfo_);
+
+ delete tapinfo_;
+}
+
+void MulticastStatisticsDialog::tapReset(void *mti_ptr)
+{
+ mcaststream_tapinfo_t *tapinfo = (mcaststream_tapinfo_t *)mti_ptr;
+ MulticastStatisticsDialog *ms_dlg = dynamic_cast<MulticastStatisticsDialog *>((MulticastStatisticsDialog*)tapinfo->user_data);
+ if (!ms_dlg || !ms_dlg->statsTreeWidget()) return;
+
+ ms_dlg->statsTreeWidget()->clear();
+}
+
+void MulticastStatisticsDialog::tapDraw(void *mti_ptr)
+{
+ mcaststream_tapinfo_t *tapinfo = (mcaststream_tapinfo_t *)mti_ptr;
+ MulticastStatisticsDialog *ms_dlg = dynamic_cast<MulticastStatisticsDialog *>((MulticastStatisticsDialog*)tapinfo->user_data);
+ if (!ms_dlg || !ms_dlg->statsTreeWidget()) return;
+
+ // Add missing rows and update stats
+ int cur_row = 0;
+ for (GList *cur = g_list_first(tapinfo->strinfo_list); cur; cur = g_list_next(cur)) {
+ mcast_stream_info_t *stream_info = (mcast_stream_info_t *) cur->data;
+ if (!stream_info) continue;
+
+ MulticastStatTreeWidgetItem *ms_ti;
+ QTreeWidgetItem *ti = ms_dlg->statsTreeWidget()->topLevelItem(cur_row);
+ if (!ti) {
+ ms_ti = new MulticastStatTreeWidgetItem(ms_dlg->statsTreeWidget());
+ for (int col = 0; col < ms_dlg->statsTreeWidget()->columnCount(); col++) {
+ if (col == col_src_addr_ || col == col_dst_addr_) continue;
+ ms_ti->setTextAlignment(col, Qt::AlignRight);
+ }
+ } else {
+ ms_ti = static_cast<MulticastStatTreeWidgetItem *>(ti);
+ }
+
+ ms_ti->updateStreamInfo(stream_info);
+ cur_row++;
+ }
+
+ for (int col = 0; col < ms_dlg->statsTreeWidget()->columnCount() - 1; col++) {
+ ms_dlg->statsTreeWidget()->resizeColumnToContents(col);
+ }
+}
+
+const QString MulticastStatisticsDialog::filterExpression()
+{
+ QString filter_expr;
+ if (statsTreeWidget()->selectedItems().count() > 0) {
+ QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0];
+
+ MulticastStatTreeWidgetItem *ms_ti = static_cast<MulticastStatTreeWidgetItem *>(ti);
+ filter_expr = ms_ti->filterExpression();
+ }
+ return filter_expr;
+}
+
+void MulticastStatisticsDialog::updateWidgets()
+{
+ QString hint;
+ bool enable_apply = true;
+ bool enable_edits = cap_file_.isValid();
+ bool ok = false;
+ int param;
+
+ param = burst_measurement_interval_le_->text().toUInt(&ok);
+ if (!ok || param < 1 || param > 1000) {
+ hint += tr("The burst interval must be between 1 and 1000. ");
+ enable_apply = false;
+ burst_measurement_interval_le_->setSyntaxState(SyntaxLineEdit::Invalid);
+ } else {
+ burst_measurement_interval_le_->setSyntaxState(SyntaxLineEdit::Valid);
+ }
+
+ param = burst_alarm_threshold_le_->text().toInt(&ok);
+ if (!ok) {
+ hint += tr("The burst alarm threshold isn't valid. ");
+ enable_apply = false;
+ burst_alarm_threshold_le_->setSyntaxState(SyntaxLineEdit::Invalid);
+ } else {
+ burst_alarm_threshold_le_->setSyntaxState(SyntaxLineEdit::Valid);
+ }
+
+ param = buffer_alarm_threshold_le_->text().toInt(&ok);
+ if (!ok || param < 1) {
+ hint += tr("The buffer alarm threshold isn't valid. ");
+ enable_apply = false;
+ buffer_alarm_threshold_le_->setSyntaxState(SyntaxLineEdit::Invalid);
+ } else {
+ buffer_alarm_threshold_le_->setSyntaxState(SyntaxLineEdit::Valid);
+ }
+
+ param = stream_empty_speed_le_->text().toInt(&ok);
+ if (!ok || param < 1 || param > 10000000) {
+ hint += tr("The stream empty speed should be between 1 and 10000000. ");
+ enable_apply = false;
+ stream_empty_speed_le_->setSyntaxState(SyntaxLineEdit::Invalid);
+ } else {
+ stream_empty_speed_le_->setSyntaxState(SyntaxLineEdit::Valid);
+ }
+
+ param = total_empty_speed_le_->text().toInt(&ok);
+ if (!ok || param < 1 || param > 10000000) {
+ hint += tr("The total empty speed should be between 1 and 10000000. ");
+ enable_apply = false;
+ total_empty_speed_le_->setSyntaxState(SyntaxLineEdit::Invalid);
+ } else {
+ total_empty_speed_le_->setSyntaxState(SyntaxLineEdit::Valid);
+ }
+
+ foreach (QWidget *line_edit, line_edits_) {
+ line_edit->setEnabled(enable_edits);
+ }
+
+ applyFilterButton()->setEnabled(enable_apply);
+
+ if (hint.isEmpty() && tapinfo_->allstreams) {
+ const QString stats = tr("%1 streams, avg bw: %2bps, max bw: %3bps, max burst: %4 / %5ms, max buffer: %6B")
+ .arg(statsTreeWidget()->topLevelItemCount())
+ .arg(bits_s_to_qstring(tapinfo_->allstreams->average_bw))
+ .arg(bits_s_to_qstring(tapinfo_->allstreams->element.maxbw))
+ .arg(tapinfo_->allstreams->element.topburstsize)
+ .arg(mcast_stream_burstint)
+ .arg(bits_s_to_qstring(tapinfo_->allstreams->element.topbuffusage));
+ hint.append(stats);
+ }
+ hint.prepend("<small><i>");
+ hint.append("</i></small>");
+ setHint(hint);
+ TapParameterDialog::updateWidgets();
+}
+
+void MulticastStatisticsDialog::updateMulticastParameters()
+{
+ bool ok = false;
+ int param;
+
+ param = burst_measurement_interval_le_->text().toUInt(&ok);
+ if (ok && param > 0 && param <= 1000) {
+ mcast_stream_burstint = (guint16) param;
+ }
+
+ param = burst_alarm_threshold_le_->text().toInt(&ok);
+ if (ok) {
+ mcast_stream_trigger = param;
+ }
+
+ param = buffer_alarm_threshold_le_->text().toInt(&ok);
+ if (ok && param > 0) {
+ mcast_stream_trigger = param;
+ }
+
+ param = stream_empty_speed_le_->text().toInt(&ok);
+ if (ok && param > 0 && param <= 10000000) {
+ mcast_stream_emptyspeed = param;
+ }
+
+ param = total_empty_speed_le_->text().toInt(&ok);
+ if (ok && param > 0 && param <= 10000000) {
+ mcast_stream_cumulemptyspeed = param;
+ }
+}
+
+void MulticastStatisticsDialog::fillTree()
+{
+ QList<QWidget *> disable_widgets = QList<QWidget *>()
+ << line_edits_ << displayFilterLineEdit() << applyFilterButton();
+
+ foreach (QWidget *w, disable_widgets) w->setEnabled(false);
+
+ /* Scan for Mcast streams (redissect all packets) */
+ mcaststream_scan(tapinfo_, cap_file_.capFile());
+ tapDraw(tapinfo_);
+
+ foreach (QWidget *w, disable_widgets) w->setEnabled(true);
+ updateWidgets();
+}
+
+void MulticastStatisticsDialog::captureFileClosing()
+{
+ /* Remove the stream tap listener */
+ remove_tap_listener_mcast_stream(tapinfo_);
+
+ updateWidgets();
+}
+
+// Stat command + args
+
+static void
+multicast_statistics_init(const char *, void*) {
+ wsApp->emitStatCommandSignal("MulticastStatistics", NULL, NULL);
+}
+
+static stat_tap_ui multicast_statistics_ui = {
+ REGISTER_STAT_GROUP_GENERIC,
+ NULL,
+ "multicast,stat",
+ multicast_statistics_init,
+ 0,
+ NULL
+};
+
+extern "C" {
+void
+register_tap_listener_qt_multicast_statistics(void)
+{
+ register_stat_tap_ui(&multicast_statistics_ui, NULL);
+}
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/multicast_statistics_dialog.h b/ui/qt/multicast_statistics_dialog.h
new file mode 100644
index 0000000000..5e6a56d7f3
--- /dev/null
+++ b/ui/qt/multicast_statistics_dialog.h
@@ -0,0 +1,72 @@
+/* multicast_statistics_dialog.h
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MULTICASTSTATISTICSDIALOG_H
+#define MULTICASTSTATISTICSDIALOG_H
+
+#include "tap_parameter_dialog.h"
+
+class SyntaxLineEdit;
+
+class MulticastStatisticsDialog : public TapParameterDialog
+{
+ Q_OBJECT
+
+public:
+ MulticastStatisticsDialog(QWidget &parent, CaptureFile &cf, const char *filter = NULL);
+ ~MulticastStatisticsDialog();
+
+private:
+ struct _mcaststream_tapinfo *tapinfo_;
+ SyntaxLineEdit *burst_measurement_interval_le_;
+ SyntaxLineEdit *burst_alarm_threshold_le_;
+ SyntaxLineEdit *buffer_alarm_threshold_le_;
+ SyntaxLineEdit *stream_empty_speed_le_;
+ SyntaxLineEdit *total_empty_speed_le_;
+ QList<QWidget *> line_edits_;
+
+ // Callbacks for register_tap_listener
+ static void tapReset(void *mti_ptr);
+ static void tapDraw(void *mti_ptr);
+
+ virtual const QString filterExpression();
+
+private slots:
+ void updateWidgets();
+ void updateMulticastParameters();
+ virtual void fillTree();
+ void captureFileClosing();
+};
+
+#endif // MULTICASTSTATISTICSDIALOG_H
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/response_time_delay_dialog.cpp b/ui/qt/response_time_delay_dialog.cpp
index dd80261c3c..2e2de37c7a 100644
--- a/ui/qt/response_time_delay_dialog.cpp
+++ b/ui/qt/response_time_delay_dialog.cpp
@@ -78,13 +78,6 @@ enum {
col_repeated_responses_
};
-QStringList header_names_ = QStringList()
- << "Type" << "Messages"
- << "Min SRT" << "Max SRT" << "Avg SRT"
- << "Min in Frame" << "Max in Frame"
- << "Open Requests" << "Discarded Responses"
- << "Repeated Requests" << "Repeated Responses";
-
enum {
rtd_table_type_ = 1000,
rtd_time_stat_type_
@@ -169,19 +162,24 @@ ResponseTimeDelayDialog::ResponseTimeDelayDialog(QWidget &parent, CaptureFile &c
TapParameterDialog(parent, cf, help_topic),
rtd_(rtd)
{
- QString subtitle = QString("%1 Response Time Delay Statistics")
+ QString subtitle = tr("%1 Response Time Delay Statistics")
.arg(proto_get_protocol_short_name(find_protocol_by_id(get_rtd_proto_id(rtd))));
setWindowSubtitle(subtitle);
- statsTreeWidget()->setHeaderLabels(header_names_);
+ QStringList header_names = QStringList()
+ << tr("Type") << tr("Messages")
+ << tr("Min SRT") << tr("Max SRT") << tr("Avg SRT")
+ << tr("Min in Frame") << tr("Max in Frame")
+ << tr("Open Requests") << tr("Discarded Responses")
+ << tr("Repeated Requests") << tr("Repeated Responses");
+
+ statsTreeWidget()->setHeaderLabels(header_names);
for (int col = 0; col < statsTreeWidget()->columnCount(); col++) {
if (col == col_type_) continue;
statsTreeWidget()->headerItem()->setTextAlignment(col, Qt::AlignRight);
}
- setDisplayFilter(filter);
-
if (!filter.isEmpty()) {
setDisplayFilter(filter);
}
diff --git a/ui/qt/service_response_time_dialog.cpp b/ui/qt/service_response_time_dialog.cpp
index b976b5f0f2..b7e1d14b23 100644
--- a/ui/qt/service_response_time_dialog.cpp
+++ b/ui/qt/service_response_time_dialog.cpp
@@ -195,49 +195,7 @@ ServiceResponseTimeDialog::ServiceResponseTimeDialog(QWidget &parent, CaptureFil
statsTreeWidget()->headerItem()->setTextAlignment(col, Qt::AlignRight);
}
- QMenu *submenu;
- QAction *insert_action = ctx_menu_.actions().first();
-
- FilterAction::Action cur_action = FilterAction::ActionApply;
- submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
- foreach (FilterAction::ActionType at, FilterAction::actionTypes()) {
- FilterAction *fa = new FilterAction(submenu, cur_action, at);
- submenu->addAction(fa);
- connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
- filter_actions_ << fa;
- }
- ctx_menu_.insertMenu(insert_action, submenu);
-
- cur_action = FilterAction::ActionPrepare;
- submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
- foreach (FilterAction::ActionType at, FilterAction::actionTypes()) {
- FilterAction *fa = new FilterAction(submenu, cur_action, at);
- submenu->addAction(fa);
- connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
- filter_actions_ << fa;
- }
- ctx_menu_.insertMenu(insert_action, submenu);
-
- cur_action = FilterAction::ActionFind;
- submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
- foreach (FilterAction::ActionType at, FilterAction::actionTypes(cur_action)) {
- FilterAction *fa = new FilterAction(submenu, cur_action, at);
- submenu->addAction(fa);
- connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
- filter_actions_ << fa;
- }
- ctx_menu_.insertMenu(insert_action, submenu);
-
- cur_action = FilterAction::ActionColorize;
- submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
- foreach (FilterAction::ActionType at, FilterAction::actionTypes(cur_action)) {
- FilterAction *fa = new FilterAction(submenu, cur_action, at);
- submenu->addAction(fa);
- connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
- filter_actions_ << fa;
- }
- ctx_menu_.insertMenu(insert_action, submenu);
- ctx_menu_.insertSeparator(insert_action);
+ addFilterActions();
if (!filter.isEmpty()) {
setDisplayFilter(filter);
diff --git a/ui/qt/tap_parameter_dialog.cpp b/ui/qt/tap_parameter_dialog.cpp
index fb2922cc10..83837105d3 100644
--- a/ui/qt/tap_parameter_dialog.cpp
+++ b/ui/qt/tap_parameter_dialog.cpp
@@ -141,6 +141,21 @@ QTreeWidget *TapParameterDialog::statsTreeWidget()
return ui->statsTreeWidget;
}
+QLineEdit *TapParameterDialog::displayFilterLineEdit()
+{
+ return ui->displayFilterLineEdit;
+}
+
+QPushButton *TapParameterDialog::applyFilterButton()
+{
+ return ui->applyFilterButton;
+}
+
+QVBoxLayout *TapParameterDialog::verticalLayout()
+{
+ return ui->verticalLayout;
+}
+
QHBoxLayout *TapParameterDialog::filterLayout()
{
return ui->filterLayout;
@@ -423,6 +438,53 @@ void TapParameterDialog::contextMenuEvent(QContextMenuEvent *event)
ctx_menu_.exec(event->globalPos());
}
+void TapParameterDialog::addFilterActions()
+{
+ QMenu *submenu;
+ QAction *insert_action = ctx_menu_.actions().first();
+
+ FilterAction::Action cur_action = FilterAction::ActionApply;
+ submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
+ foreach (FilterAction::ActionType at, FilterAction::actionTypes()) {
+ FilterAction *fa = new FilterAction(submenu, cur_action, at);
+ submenu->addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ filter_actions_ << fa;
+ }
+ ctx_menu_.insertMenu(insert_action, submenu);
+
+ cur_action = FilterAction::ActionPrepare;
+ submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
+ foreach (FilterAction::ActionType at, FilterAction::actionTypes()) {
+ FilterAction *fa = new FilterAction(submenu, cur_action, at);
+ submenu->addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ filter_actions_ << fa;
+ }
+ ctx_menu_.insertMenu(insert_action, submenu);
+
+ cur_action = FilterAction::ActionFind;
+ submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
+ foreach (FilterAction::ActionType at, FilterAction::actionTypes(cur_action)) {
+ FilterAction *fa = new FilterAction(submenu, cur_action, at);
+ submenu->addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ filter_actions_ << fa;
+ }
+ ctx_menu_.insertMenu(insert_action, submenu);
+
+ cur_action = FilterAction::ActionColorize;
+ submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
+ foreach (FilterAction::ActionType at, FilterAction::actionTypes(cur_action)) {
+ FilterAction *fa = new FilterAction(submenu, cur_action, at);
+ submenu->addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ filter_actions_ << fa;
+ }
+ ctx_menu_.insertMenu(insert_action, submenu);
+ ctx_menu_.insertSeparator(insert_action);
+}
+
void TapParameterDialog::updateWidgets()
{
if (file_closed_) {
diff --git a/ui/qt/tap_parameter_dialog.h b/ui/qt/tap_parameter_dialog.h
index c9188829fb..281274b298 100644
--- a/ui/qt/tap_parameter_dialog.h
+++ b/ui/qt/tap_parameter_dialog.h
@@ -35,8 +35,10 @@
#include "wireshark_dialog.h"
class QHBoxLayout;
+class QLineEdit;
class QTreeWidget;
class QTreeWidgetItem;
+class QVBoxLayout;
namespace Ui {
class TapParameterDialog;
@@ -60,6 +62,9 @@ public:
// Needed by static member functions in subclasses. Should we just make
// "ui" available instead?
QTreeWidget *statsTreeWidget();
+ QLineEdit *displayFilterLineEdit();
+ QPushButton *applyFilterButton();
+ QVBoxLayout *verticalLayout();
QHBoxLayout *filterLayout();
void drawTreeItems();
@@ -71,11 +76,9 @@ signals:
public slots:
protected:
- QMenu ctx_menu_;
- QList<QAction *> filter_actions_;
-
void showEvent(QShowEvent *);
void contextMenuEvent(QContextMenuEvent *event);
+ void addFilterActions();
QString displayFilter();
void setDisplayFilter(const QString &filter);
void setHint(const QString &hint);
@@ -84,9 +87,12 @@ protected:
protected slots:
void filterActionTriggered();
+ void updateWidgets();
private:
Ui::TapParameterDialog *ui;
+ QMenu ctx_menu_;
+ QList<QAction *> filter_actions_;
int help_topic_;
static const QString action_name_;
bool retap_on_show_;
@@ -99,7 +105,6 @@ private:
virtual QByteArray getTreeAsString(st_format_type format);
private slots:
- void updateWidgets();
void on_applyFilterButton_clicked();
void on_actionCopyToClipboard_triggered();
void on_actionSaveAs_triggered();
diff --git a/ui/qt/tap_parameter_dialog.ui b/ui/qt/tap_parameter_dialog.ui
index c7c624fc1c..bcaad122ea 100644
--- a/ui/qt/tap_parameter_dialog.ui
+++ b/ui/qt/tap_parameter_dialog.ui
@@ -16,6 +16,9 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="statsTreeWidget">
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
<column>
<property name="text">
<string notr="true">Item</string>
diff --git a/ui/rtp_stream.h b/ui/rtp_stream.h
index f6097561ff..2df54e9a03 100644
--- a/ui/rtp_stream.h
+++ b/ui/rtp_stream.h
@@ -106,7 +106,6 @@ struct _rtpstream_tapinfo {
rtp_stream_info_t *filter_stream_fwd; /**< used as filter in some tap modes */
rtp_stream_info_t *filter_stream_rev; /**< used as filter in some tap modes */
FILE *save_file;
- guint32 launch_count; /**< number of times the tap has been run */
gboolean is_registered; /**< if the tap listener is currently registered or not */
};
diff --git a/ui/tap-rtp-common.c b/ui/tap-rtp-common.c
index a95e261b50..b164c39ed3 100644
--- a/ui/tap-rtp-common.c
+++ b/ui/tap-rtp-common.c
@@ -94,8 +94,6 @@ void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
tapinfo->npackets = 0;
}
- ++(tapinfo->launch_count);
-
return;
}
diff --git a/wsutil/str_util.c b/wsutil/str_util.c
index ba1c486282..adcbb91e03 100644
--- a/wsutil/str_util.c
+++ b/wsutil/str_util.c
@@ -121,6 +121,7 @@ isdigit_string(guchar *str)
#endif
/* Given a size, return its value in a human-readable format */
+/* This doesn't handle fractional values. We might want to make size a double. */
gchar *
format_size(gint64 size, format_size_flags_e flags)
{