forked from osmocom/wireshark
Qt: Conversation time column updates.
Add a checkbox which lets you toggle between absolute and relative start times. Use the local time for now. Fixes bug 11618. Adjust our time precision based on the capture file's time precision. Fixes bug 12803. Update the User's Guide accordingly. Bug: 11618 Bug: 12803 Change-Id: I0049d6db6e4d0b6967bf35e6d056a61bfb4de10f Reviewed-on: https://code.wireshark.org/review/17448 Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
parent
df3bf9ca79
commit
5846524f0b
Binary file not shown.
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 235 KiB |
|
@ -141,10 +141,10 @@ description of the known endpoint types can be found in
|
|||
The conversations window is similar to the endpoint Window. See
|
||||
<<ChStatEndpointsWindow>> for a description of their common features. Along with
|
||||
addresses, packet counters, and byte counters the conversation window adds four
|
||||
columns: the time in seconds between the start of the capture and the start of
|
||||
the conversation (``Rel Start''), the duration of the conversation in seconds, and
|
||||
the average bits (not bytes) per second in each direction. A timeline graph is
|
||||
also drawn across the ``Rel Start'' and ``Duration'' columns.
|
||||
columns: the start time of the conversation (``Rel Start'') or (``Abs Start''),
|
||||
the duration of the conversation in seconds, and the average bits (not bytes)
|
||||
per second in each direction. A timeline graph is also drawn across the
|
||||
``Rel Start'' / ``Abs Start'' and ``Duration'' columns.
|
||||
|
||||
.The ``Conversations'' window
|
||||
image::wsug_graphics/ws-stats-conversations.png[scaledwidth="100%"]
|
||||
|
@ -154,7 +154,10 @@ Each row in the list shows the statistical values for exactly one conversation.
|
|||
_Name resolution_ will be done if selected in the window and if it is active for
|
||||
the specific protocol layer (MAC layer for the selected Ethernet endpoints
|
||||
page). _Limit to display filter_ will only show conversations matching the
|
||||
current display filter.
|
||||
current display filter. _Absolute start time_ switches the start time column
|
||||
between relative (``Rel Start'') and absolute (``Abs Start'') times. Relative start
|
||||
times match the ``Seconds Since Beginning of Capture'' time display format in the
|
||||
packet list and absolute start times match the ``Time of Day'' display format.
|
||||
|
||||
The button:[Copy] button will copy the list values to the clipboard in CSV
|
||||
(Comma Separated Values) or YAML format. The button:[Follow Stream...] button
|
||||
|
|
|
@ -48,7 +48,7 @@ col_format_to_string(const gint fmt) {
|
|||
"%At", /* 3) COL_ABS_TIME */
|
||||
"%V", /* 4) COL_VSAN - !! DEPRECATED !!*/
|
||||
"%B", /* 5) COL_CUMULATIVE_BYTES */
|
||||
"%Cus", /* 6 COL_CUSTOM */
|
||||
"%Cus", /* 6) COL_CUSTOM */
|
||||
"%y", /* 7) COL_DCE_CALL */
|
||||
"%Tt", /* 8) COL_DELTA_TIME */
|
||||
"%Gt", /* 9) COL_DELTA_TIME_DIS */
|
||||
|
|
|
@ -99,6 +99,14 @@ struct _packet_info *CaptureFile::packetInfo()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int CaptureFile::timestampPrecision()
|
||||
{
|
||||
if (capFile() && capFile()->wth) {
|
||||
return wtap_file_tsprec(capFile()->wth);
|
||||
}
|
||||
return WTAP_TSPREC_UNKNOWN;
|
||||
}
|
||||
|
||||
void CaptureFile::retapPackets()
|
||||
{
|
||||
if (cap_file_) {
|
||||
|
|
|
@ -76,6 +76,12 @@ public:
|
|||
*/
|
||||
struct _packet_info *packetInfo();
|
||||
|
||||
/** Timestamp precision for the current file.
|
||||
* @return One of the WTAP_TSPREC_x values defined in wiretap/wtap.h,
|
||||
* or WTAP_TSPREC_UNKNOWN if no file is open.
|
||||
*/
|
||||
int timestampPrecision();
|
||||
|
||||
/** Reload the capture file
|
||||
*/
|
||||
void reload();
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "wireshark_application.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDateTime>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
|
||||
|
@ -58,6 +59,9 @@
|
|||
// Fixed bugs:
|
||||
// - Friendly unit displays https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9231
|
||||
// - Misleading bps calculation https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8703
|
||||
// - Show Absolute time in conversation tables https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11618
|
||||
// - The value of 'Rel start' and 'Duration' in "Conversations" no need too precise https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=12803
|
||||
|
||||
|
||||
static const QString table_name_ = QObject::tr("Conversation");
|
||||
ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf, int cli_proto_id, const char *filter) :
|
||||
|
@ -71,6 +75,8 @@ ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf, int cli
|
|||
graph_bt_->setToolTip(tr("Graph a TCP conversation."));
|
||||
connect(graph_bt_, SIGNAL(clicked()), this, SLOT(graphTcp()));
|
||||
|
||||
absoluteTimeCheckBox()->show();
|
||||
|
||||
addProgressFrame(&parent);
|
||||
|
||||
QList<int> conv_protos;
|
||||
|
@ -163,6 +169,9 @@ bool ConversationDialog::addTrafficTable(register_ct_t* table)
|
|||
this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
|
||||
connect(nameResolutionCheckBox(), SIGNAL(toggled(bool)),
|
||||
conv_tree, SLOT(setNameResolutionEnabled(bool)));
|
||||
connect(absoluteTimeCheckBox(), SIGNAL(toggled(bool)),
|
||||
conv_tree, SLOT(updateStartTime(bool)));
|
||||
|
||||
|
||||
// XXX Move to ConversationTreeWidget ctor?
|
||||
QByteArray filter_utf8;
|
||||
|
@ -365,9 +374,31 @@ public:
|
|||
case CONV_COLUMN_BYTES_BA:
|
||||
return gchar_free_to_qstring(format_size(conv_item->rx_bytes, format_size_unit_none|format_size_prefix_si));
|
||||
case CONV_COLUMN_START:
|
||||
return QString::number(nstime_to_sec(&conv_item->start_time), 'f', 9);
|
||||
{
|
||||
bool use_ns = treeWidget()->window()->property("nanosecond_precision").toBool();
|
||||
int width = use_ns ? 9 : 6;
|
||||
|
||||
if (treeWidget()->window()->property("absolute_start_time").toBool()) {
|
||||
nstime_t *abs_time = &conv_item->start_abs_time;
|
||||
QDateTime abs_dt = QDateTime::fromMSecsSinceEpoch(nstime_to_msec(abs_time));
|
||||
return QString("%1.%2")
|
||||
// Mimic column-utils:set_abs_time as best we can
|
||||
.arg(abs_dt.toString("hh:mm:ss"))
|
||||
.arg(use_ns ? abs_time->nsecs : abs_time->nsecs / 1000, width, 10, QChar('0'));
|
||||
}
|
||||
|
||||
return QString::number(nstime_to_sec(&conv_item->start_time), 'f', width);
|
||||
}
|
||||
case CONV_COLUMN_DURATION:
|
||||
return QString::number(duration, 'f', 6);
|
||||
{
|
||||
// The GTK+ UI uses 9 digit precision for the start time and 4 for the duration.
|
||||
// Do the same here and above for non-nanosecond precision and add a couple
|
||||
// of digits for nanosecond precision.
|
||||
bool use_ns = treeWidget()->window()->property("nanosecond_precision").toBool();
|
||||
int width = use_ns ? 6 : 4;
|
||||
|
||||
return QString::number(duration, 'f', width);
|
||||
}
|
||||
case CONV_COLUMN_BPS_AB:
|
||||
if (duration > min_bw_calc_duration_) {
|
||||
bps_ab = gchar_free_to_qstring(format_size((gint64) conv_item->tx_bytes * 8 / duration, format_size_unit_none|format_size_prefix_si));
|
||||
|
@ -665,6 +696,19 @@ void ConversationTreeWidget::tapDraw(void *conv_hash_ptr)
|
|||
conv_tree->updateItems();
|
||||
}
|
||||
|
||||
void ConversationTreeWidget::updateStartTime(bool absolute)
|
||||
{
|
||||
headerItem()->setText(CONV_COLUMN_START, absolute
|
||||
? conv_abs_start_title
|
||||
: conv_column_titles[CONV_COLUMN_START]);
|
||||
|
||||
dataChanged(QModelIndex(), QModelIndex());
|
||||
|
||||
if (topLevelItemCount() > 0) {
|
||||
resizeColumnToContents(CONV_COLUMN_START);
|
||||
}
|
||||
}
|
||||
|
||||
QMap<FilterAction::ActionDirection, conv_direction_e> fad_to_cd_;
|
||||
|
||||
void ConversationTreeWidget::initDirectionMap()
|
||||
|
|
|
@ -38,6 +38,9 @@ public:
|
|||
double minRelStartTime() { return min_rel_start_time_; }
|
||||
double maxRelStopTime() { return max_rel_stop_time_; }
|
||||
|
||||
public slots:
|
||||
void updateStartTime(bool absolute);
|
||||
|
||||
private:
|
||||
void initDirectionMap();
|
||||
void updateItems();
|
||||
|
|
|
@ -56,12 +56,14 @@ TrafficTableDialog::TrafficTableDialog(QWidget &parent, CaptureFile &cf, const c
|
|||
ui(new Ui::TrafficTableDialog),
|
||||
cap_file_(cf),
|
||||
file_closed_(false),
|
||||
filter_(filter)
|
||||
filter_(filter),
|
||||
nanosecond_timestamps_(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
loadGeometry(parent.width(), parent.height() * 3 / 4);
|
||||
|
||||
ui->enabledTypesPushButton->setText(tr("%1 Types").arg(table_name));
|
||||
ui->absoluteTimeCheckBox->hide();
|
||||
setWindowSubtitle(QString("%1s").arg(table_name));
|
||||
|
||||
QMenu *copy_menu = new QMenu();
|
||||
|
@ -78,6 +80,10 @@ TrafficTableDialog::TrafficTableDialog(QWidget &parent, CaptureFile &cf, const c
|
|||
ui->enabledTypesPushButton->setMenu(&traffic_type_menu_);
|
||||
ui->trafficTableTabWidget->setFocus();
|
||||
|
||||
if (cf.timestampPrecision() == WTAP_TSPREC_NSEC) {
|
||||
nanosecond_timestamps_ = true;
|
||||
}
|
||||
|
||||
connect(wsApp, SIGNAL(addressResolutionChanged()), this, SLOT(currentTabChanged()));
|
||||
connect(wsApp, SIGNAL(addressResolutionChanged()), this, SLOT(updateWidgets()));
|
||||
connect(ui->trafficTableTabWidget, SIGNAL(currentChanged(int)),
|
||||
|
@ -93,6 +99,11 @@ TrafficTableDialog::~TrafficTableDialog()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
bool TrafficTableDialog::absoluteStartTime()
|
||||
{
|
||||
return absoluteTimeCheckBox()->isChecked();
|
||||
}
|
||||
|
||||
const QList<int> TrafficTableDialog::defaultProtos() const
|
||||
{
|
||||
// Reasonable defaults?
|
||||
|
@ -144,6 +155,11 @@ QCheckBox *TrafficTableDialog::nameResolutionCheckBox() const
|
|||
return ui->nameResolutionCheckBox;
|
||||
}
|
||||
|
||||
QCheckBox *TrafficTableDialog::absoluteTimeCheckBox() const
|
||||
{
|
||||
return ui->absoluteTimeCheckBox;
|
||||
}
|
||||
|
||||
QPushButton *TrafficTableDialog::enabledTypesPushButton() const
|
||||
{
|
||||
return ui->enabledTypesPushButton;
|
||||
|
|
|
@ -103,6 +103,8 @@ signals:
|
|||
class TrafficTableDialog : public WiresharkDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool absolute_start_time READ absoluteStartTime)
|
||||
Q_PROPERTY(bool nanosecond_timestamps READ nanosecondTimestamps)
|
||||
|
||||
public:
|
||||
/** Create a new conversation window.
|
||||
|
@ -115,6 +117,16 @@ public:
|
|||
explicit TrafficTableDialog(QWidget &parent, CaptureFile &cf, const char *filter = NULL, const QString &table_name = tr("Unknown"));
|
||||
~TrafficTableDialog();
|
||||
|
||||
/** Use absolute start times.
|
||||
* @return true if the "Absolute start time" checkbox is checked, false otherwise.
|
||||
*/
|
||||
bool absoluteStartTime();
|
||||
|
||||
/** Use nanosecond timestamps.
|
||||
* @return true if the current capture file uses nanosecond timestamps, false otherwise.
|
||||
*/
|
||||
bool nanosecondTimestamps() { return nanosecond_timestamps_; }
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
|
@ -143,6 +155,7 @@ protected:
|
|||
QTabWidget *trafficTableTabWidget() const;
|
||||
QCheckBox *displayFilterCheckBox() const;
|
||||
QCheckBox *nameResolutionCheckBox() const;
|
||||
QCheckBox *absoluteTimeCheckBox() const;
|
||||
QPushButton *enabledTypesPushButton() const;
|
||||
|
||||
protected slots:
|
||||
|
@ -151,6 +164,7 @@ protected slots:
|
|||
|
||||
private:
|
||||
QString window_name_;
|
||||
bool nanosecond_timestamps_;
|
||||
|
||||
QList<QVariant> curTreeRowData(int row) const;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<widget class="QTabWidget" name="trafficTableTabWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,1,0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,1,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="nameResolutionCheckBox">
|
||||
<property name="toolTip">
|
||||
|
@ -49,6 +49,29 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="absoluteTimeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Show absolute times in the start time column.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Absolute start time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -83,6 +106,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
|
|
|
@ -65,6 +65,7 @@ const char *conv_column_titles[CONV_NUM_COLUMNS] = {
|
|||
|
||||
const char *conv_conn_a_title = "Connection A";
|
||||
const char *conv_conn_b_title = "Connection B";
|
||||
const char *conv_abs_start_title = "Abs Start";
|
||||
|
||||
const char *endp_column_titles[ENDP_NUM_COLUMNS] = {
|
||||
"Address",
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef enum {
|
|||
extern const char *conv_column_titles[CONV_NUM_COLUMNS];
|
||||
extern const char *conv_conn_a_title;
|
||||
extern const char *conv_conn_b_title;
|
||||
extern const char *conv_abs_start_title;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue