2013-12-13 11:29:11 +00:00
|
|
|
/* sctp_graph_dialog.cpp
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-04-30 07:47:58 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2013-12-13 11:29:11 +00:00
|
|
|
|
2015-10-04 17:10:29 +00:00
|
|
|
#include <wsutil/utf8_entities.h>
|
2014-12-31 22:21:50 +00:00
|
|
|
|
2013-12-13 07:25:30 +00:00
|
|
|
#include "sctp_graph_dialog.h"
|
2015-06-25 16:17:03 +00:00
|
|
|
#include <ui_sctp_graph_dialog.h>
|
2013-12-18 13:49:10 +00:00
|
|
|
#include "sctp_assoc_analyse_dialog.h"
|
2013-12-13 07:25:30 +00:00
|
|
|
|
2015-02-12 23:35:59 +00:00
|
|
|
#include <file.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <epan/dissectors/packet-sctp.h>
|
|
|
|
#include "epan/packet.h"
|
|
|
|
|
|
|
|
#include "ui/tap-sctp-analysis.h"
|
|
|
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
2018-05-26 11:32:06 +00:00
|
|
|
#include <ui/qt/utils/qt_ui_utils.h>
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/widgets/qcustomplot.h>
|
2018-05-16 00:02:26 +00:00
|
|
|
#include "ui/qt/widgets/wireshark_file_dialog.h"
|
2022-02-01 03:30:09 +00:00
|
|
|
#include "main_application.h"
|
2013-12-13 07:25:30 +00:00
|
|
|
|
2018-08-15 19:46:39 +00:00
|
|
|
SCTPGraphDialog::SCTPGraphDialog(QWidget *parent, const sctp_assoc_info_t *assoc,
|
|
|
|
capture_file *cf, int dir) :
|
2013-12-13 07:25:30 +00:00
|
|
|
QDialog(parent),
|
|
|
|
ui(new Ui::SCTPGraphDialog),
|
|
|
|
cap_file_(cf),
|
2016-07-03 20:37:42 +00:00
|
|
|
frame_num(0),
|
|
|
|
direction(dir),
|
2018-06-06 09:57:21 +00:00
|
|
|
relative(false),
|
|
|
|
type(1)
|
2013-12-13 07:25:30 +00:00
|
|
|
{
|
2018-08-15 19:46:39 +00:00
|
|
|
Q_ASSERT(assoc);
|
|
|
|
selected_assoc_id = assoc->assoc_id;
|
|
|
|
|
2013-12-13 07:25:30 +00:00
|
|
|
ui->setupUi(this);
|
2014-11-17 07:51:12 +00:00
|
|
|
Qt::WindowFlags flags = Qt::Window | Qt::WindowSystemMenuHint
|
|
|
|
| Qt::WindowMinimizeButtonHint
|
|
|
|
| Qt::WindowMaximizeButtonHint
|
|
|
|
| Qt::WindowCloseButtonHint;
|
|
|
|
this->setWindowFlags(flags);
|
2018-08-15 19:46:39 +00:00
|
|
|
this->setWindowTitle(QString(tr("SCTP TSNs and SACKs over Time: %1 Port1 %2 Port2 %3"))
|
|
|
|
.arg(gchar_free_to_qstring(cf_get_display_name(cap_file_))).arg(assoc->port1).arg(assoc->port2));
|
|
|
|
if ((direction == 1 && assoc->n_array_tsn1 == 0) || (direction == 2 && assoc->n_array_tsn2 == 0)) {
|
2013-12-13 07:25:30 +00:00
|
|
|
QMessageBox msgBox;
|
2013-12-17 10:22:00 +00:00
|
|
|
msgBox.setText(tr("No Data Chunks sent"));
|
2013-12-13 07:25:30 +00:00
|
|
|
msgBox.exec();
|
|
|
|
return;
|
|
|
|
} else {
|
2018-08-15 19:46:39 +00:00
|
|
|
drawGraph(assoc);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SCTPGraphDialog::~SCTPGraphDialog()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
2018-08-15 19:46:39 +00:00
|
|
|
void SCTPGraphDialog::drawNRSACKGraph(const sctp_assoc_info_t* selected_assoc)
|
2013-12-13 07:25:30 +00:00
|
|
|
{
|
2019-08-14 08:18:51 +00:00
|
|
|
tsn_t *sack = Q_NULLPTR;
|
|
|
|
GList *list = Q_NULLPTR, *tlist = Q_NULLPTR;
|
2013-12-13 07:25:30 +00:00
|
|
|
guint16 gap_start=0, gap_end=0, i, numberOf_gaps, numberOf_nr_gaps;
|
|
|
|
guint8 type;
|
2018-06-06 09:57:21 +00:00
|
|
|
guint32 tsnumber, j = 0, min_tsn, rel = 0;
|
2019-08-14 08:18:51 +00:00
|
|
|
struct nr_sack_chunk_header *nr_sack_header = Q_NULLPTR;
|
|
|
|
struct gaps *nr_gap = Q_NULLPTR;
|
2013-12-13 07:25:30 +00:00
|
|
|
/* This holds the sum of gap acks and nr gap acks */
|
|
|
|
guint16 total_gaps = 0;
|
|
|
|
|
|
|
|
if (direction == 1) {
|
|
|
|
list = g_list_last(selected_assoc->sack1);
|
|
|
|
min_tsn = selected_assoc->min_tsn1;
|
|
|
|
} else {
|
2015-10-05 13:55:40 +00:00
|
|
|
list = g_list_last(selected_assoc->sack2);
|
|
|
|
min_tsn = selected_assoc->min_tsn2;
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2018-06-06 09:57:21 +00:00
|
|
|
if (relative) {
|
|
|
|
rel = min_tsn;
|
|
|
|
}
|
2013-12-13 07:25:30 +00:00
|
|
|
while (list) {
|
2019-08-14 08:18:51 +00:00
|
|
|
sack = gxx_list_data(tsn_t*, list);
|
2013-12-13 07:25:30 +00:00
|
|
|
tlist = g_list_first(sack->tsns);
|
|
|
|
while (tlist) {
|
2019-08-14 08:18:51 +00:00
|
|
|
type = gxx_list_data(struct chunk_header *, tlist)->type;
|
2013-12-13 07:25:30 +00:00
|
|
|
if (type == SCTP_NR_SACK_CHUNK_ID) {
|
2019-08-14 08:18:51 +00:00
|
|
|
nr_sack_header = gxx_list_data(struct nr_sack_chunk_header *, tlist);
|
2013-12-13 07:25:30 +00:00
|
|
|
numberOf_nr_gaps=g_ntohs(nr_sack_header->nr_of_nr_gaps);
|
|
|
|
numberOf_gaps=g_ntohs(nr_sack_header->nr_of_gaps);
|
|
|
|
tsnumber = g_ntohl(nr_sack_header->cum_tsn_ack);
|
|
|
|
total_gaps = numberOf_gaps + numberOf_nr_gaps;
|
|
|
|
/* If the number of nr_gaps is greater than 0 */
|
2016-01-23 12:18:30 +00:00
|
|
|
if (total_gaps > 0) {
|
2013-12-13 07:25:30 +00:00
|
|
|
nr_gap = &nr_sack_header->gaps[0];
|
|
|
|
for (i = 0; i < total_gaps; i++) {
|
|
|
|
gap_start = g_ntohs(nr_gap->start);
|
|
|
|
gap_end = g_ntohs(nr_gap->end);
|
2016-01-23 12:18:30 +00:00
|
|
|
for (j = gap_start; j <= gap_end; j++) {
|
2013-12-13 07:25:30 +00:00
|
|
|
if (i >= numberOf_gaps) {
|
2018-06-06 09:57:21 +00:00
|
|
|
yn.append(j + tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xn.append(sack->secs + sack->usecs/1000000.0);
|
|
|
|
fn.append(sack->frame_number);
|
|
|
|
} else {
|
2018-06-06 09:57:21 +00:00
|
|
|
yg.append(j + tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xg.append(sack->secs + sack->usecs/1000000.0);
|
|
|
|
fg.append(sack->frame_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < total_gaps-1)
|
|
|
|
nr_gap++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tsnumber>=min_tsn) {
|
2018-06-06 09:57:21 +00:00
|
|
|
ys.append(j + tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xs.append(sack->secs + sack->usecs/1000000.0);
|
|
|
|
fs.append(sack->frame_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-14 08:18:51 +00:00
|
|
|
tlist = gxx_list_next(tlist);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2019-08-14 08:18:51 +00:00
|
|
|
list = gxx_list_previous(list);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-15 19:46:39 +00:00
|
|
|
void SCTPGraphDialog::drawSACKGraph(const sctp_assoc_info_t* selected_assoc)
|
2013-12-13 07:25:30 +00:00
|
|
|
{
|
2019-08-14 08:18:51 +00:00
|
|
|
GList *listSACK = Q_NULLPTR, *tlist = Q_NULLPTR;
|
2013-12-13 07:25:30 +00:00
|
|
|
guint16 gap_start=0, gap_end=0, nr, dup_nr;
|
2019-08-14 08:18:51 +00:00
|
|
|
struct sack_chunk_header *sack_header = Q_NULLPTR;
|
|
|
|
struct gaps *gap = Q_NULLPTR;
|
|
|
|
tsn_t *tsn = Q_NULLPTR;
|
2013-12-13 07:25:30 +00:00
|
|
|
guint8 type;
|
2018-06-06 09:57:21 +00:00
|
|
|
guint32 tsnumber=0, rel = 0;
|
2013-12-13 07:25:30 +00:00
|
|
|
guint32 minTSN;
|
2019-08-14 08:18:51 +00:00
|
|
|
guint32 *dup_list = Q_NULLPTR;
|
2013-12-13 07:25:30 +00:00
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (direction == 1) {
|
|
|
|
minTSN = selected_assoc->min_tsn1;
|
|
|
|
listSACK = g_list_last(selected_assoc->sack1);
|
|
|
|
} else {
|
|
|
|
minTSN = selected_assoc->min_tsn2;
|
|
|
|
listSACK = g_list_last(selected_assoc->sack2);
|
|
|
|
}
|
2018-06-06 09:57:21 +00:00
|
|
|
if (relative) {
|
|
|
|
rel = minTSN;
|
|
|
|
}
|
2013-12-13 07:25:30 +00:00
|
|
|
while (listSACK) {
|
2019-08-14 08:18:51 +00:00
|
|
|
tsn = gxx_list_data(tsn_t*, listSACK);
|
2013-12-13 07:25:30 +00:00
|
|
|
tlist = g_list_first(tsn->tsns);
|
|
|
|
while (tlist) {
|
2019-08-14 08:18:51 +00:00
|
|
|
type = gxx_list_data(struct chunk_header *, tlist)->type;
|
2013-12-13 07:25:30 +00:00
|
|
|
if (type == SCTP_SACK_CHUNK_ID) {
|
2019-08-14 08:18:51 +00:00
|
|
|
sack_header = gxx_list_data(struct sack_chunk_header *, tlist);
|
2013-12-13 07:25:30 +00:00
|
|
|
nr=g_ntohs(sack_header->nr_of_gaps);
|
|
|
|
tsnumber = g_ntohl(sack_header->cum_tsn_ack);
|
|
|
|
dup_nr=g_ntohs(sack_header->nr_of_dups);
|
|
|
|
if (nr>0) { // Gap Reports green
|
|
|
|
gap = &sack_header->gaps[0];
|
2019-11-17 19:02:20 +00:00
|
|
|
for (i=0;i<nr; i++) {
|
2013-12-13 07:25:30 +00:00
|
|
|
gap_start=g_ntohs(gap->start);
|
|
|
|
gap_end = g_ntohs(gap->end);
|
|
|
|
for (j=gap_start; j<=gap_end; j++) {
|
2018-06-06 09:57:21 +00:00
|
|
|
yg.append(j + tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xg.append(tsn->secs + tsn->usecs/1000000.0);
|
|
|
|
fg.append(tsn->frame_number);
|
|
|
|
}
|
|
|
|
if (i < nr-1)
|
|
|
|
gap++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tsnumber>=minTSN) { // CumTSNAck red
|
2018-06-06 09:57:21 +00:00
|
|
|
ys.append(tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xs.append(tsn->secs + tsn->usecs/1000000.0);
|
|
|
|
fs.append(tsn->frame_number);
|
|
|
|
}
|
|
|
|
if (dup_nr > 0) { // Duplicates cyan
|
|
|
|
dup_list = &sack_header->a_rwnd + 2 + nr;
|
|
|
|
for (i = 0; i < dup_nr; i++) {
|
|
|
|
tsnumber = g_ntohl(dup_list[i]);
|
|
|
|
if (tsnumber >= minTSN) {
|
2018-06-06 09:57:21 +00:00
|
|
|
yd.append(tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xd.append(tsn->secs + tsn->usecs/1000000.0);
|
|
|
|
fd.append(tsn->frame_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-14 08:18:51 +00:00
|
|
|
tlist = gxx_list_next(tlist);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2019-08-14 08:18:51 +00:00
|
|
|
listSACK = gxx_list_previous(listSACK);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QCPScatterStyle myScatter;
|
|
|
|
myScatter.setShape(QCPScatterStyle::ssCircle);
|
|
|
|
myScatter.setSize(3);
|
|
|
|
|
|
|
|
int graphcount = ui->sctpPlot->graphCount();
|
|
|
|
// create graph and assign data to it:
|
|
|
|
|
|
|
|
// Add SACK graph
|
|
|
|
if (xs.size() > 0) {
|
2013-12-17 09:51:34 +00:00
|
|
|
QCPGraph *gr = ui->sctpPlot->addGraph();
|
|
|
|
gr->setName(QString("SACK"));
|
2013-12-13 07:25:30 +00:00
|
|
|
myScatter.setPen(QPen(Qt::red));
|
|
|
|
myScatter.setBrush(Qt::red);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setData(xs, ys);
|
2013-12-17 10:22:00 +00:00
|
|
|
typeStrings.insert(graphcount, QString(tr("CumTSNAck")));
|
2013-12-13 07:25:30 +00:00
|
|
|
graphcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add Gap Acks
|
|
|
|
if (xg.size() > 0) {
|
2013-12-17 09:51:34 +00:00
|
|
|
QCPGraph *gr = ui->sctpPlot->addGraph();
|
|
|
|
gr->setName(QString("GAP"));
|
2013-12-13 07:25:30 +00:00
|
|
|
myScatter.setPen(QPen(Qt::green));
|
|
|
|
myScatter.setBrush(Qt::green);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setData(xg, yg);
|
2013-12-17 10:22:00 +00:00
|
|
|
typeStrings.insert(graphcount, QString(tr("Gap Ack")));
|
2013-12-13 07:25:30 +00:00
|
|
|
graphcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add NR Gap Acks
|
|
|
|
if (xn.size() > 0) {
|
2013-12-17 09:51:34 +00:00
|
|
|
QCPGraph *gr = ui->sctpPlot->addGraph();
|
|
|
|
gr->setName(QString("NR_GAP"));
|
2013-12-13 07:25:30 +00:00
|
|
|
myScatter.setPen(QPen(Qt::blue));
|
|
|
|
myScatter.setBrush(Qt::blue);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone);
|
2015-01-03 19:26:08 +00:00
|
|
|
ui->sctpPlot->graph(graphcount)->setData(xn, yn);
|
2013-12-17 10:22:00 +00:00
|
|
|
typeStrings.insert(graphcount, QString(tr("NR Gap Ack")));
|
2013-12-13 07:25:30 +00:00
|
|
|
graphcount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add Duplicates
|
|
|
|
if (xd.size() > 0) {
|
2013-12-17 09:51:34 +00:00
|
|
|
QCPGraph *gr = ui->sctpPlot->addGraph();
|
|
|
|
gr->setName(QString("DUP"));
|
2013-12-13 07:25:30 +00:00
|
|
|
myScatter.setPen(QPen(Qt::cyan));
|
|
|
|
myScatter.setBrush(Qt::cyan);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setData(xd, yd);
|
2013-12-17 10:22:00 +00:00
|
|
|
typeStrings.insert(graphcount, QString(tr("Duplicate Ack")));
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-15 19:46:39 +00:00
|
|
|
void SCTPGraphDialog::drawTSNGraph(const sctp_assoc_info_t* selected_assoc)
|
2013-12-13 07:25:30 +00:00
|
|
|
{
|
2019-08-14 08:18:51 +00:00
|
|
|
GList *listTSN = Q_NULLPTR,*tlist = Q_NULLPTR;
|
|
|
|
tsn_t *tsn = Q_NULLPTR;
|
2013-12-13 07:25:30 +00:00
|
|
|
guint8 type;
|
2018-06-06 09:57:21 +00:00
|
|
|
guint32 tsnumber=0, rel = 0, minTSN;
|
2013-12-13 07:25:30 +00:00
|
|
|
|
|
|
|
if (direction == 1) {
|
|
|
|
listTSN = g_list_last(selected_assoc->tsn1);
|
2018-06-06 09:57:21 +00:00
|
|
|
minTSN = selected_assoc->min_tsn1;
|
2013-12-13 07:25:30 +00:00
|
|
|
} else {
|
|
|
|
listTSN = g_list_last(selected_assoc->tsn2);
|
2018-06-06 09:57:21 +00:00
|
|
|
minTSN = selected_assoc->min_tsn2;
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
|
2018-06-06 09:57:21 +00:00
|
|
|
if (relative) {
|
|
|
|
rel = minTSN;
|
|
|
|
}
|
|
|
|
|
2013-12-13 07:25:30 +00:00
|
|
|
while (listTSN) {
|
2019-08-14 08:18:51 +00:00
|
|
|
tsn = gxx_list_data(tsn_t*, listTSN);
|
2013-12-13 07:25:30 +00:00
|
|
|
tlist = g_list_first(tsn->tsns);
|
|
|
|
while (tlist)
|
|
|
|
{
|
2019-08-14 08:18:51 +00:00
|
|
|
type = gxx_list_data(struct chunk_header *, tlist)->type;
|
2015-10-05 13:55:40 +00:00
|
|
|
if (type == SCTP_DATA_CHUNK_ID || type == SCTP_I_DATA_CHUNK_ID || type == SCTP_FORWARD_TSN_CHUNK_ID) {
|
2019-08-14 08:18:51 +00:00
|
|
|
tsnumber = g_ntohl(gxx_list_data(struct data_chunk_header *, tlist)->tsn);
|
2018-06-06 09:57:21 +00:00
|
|
|
yt.append(tsnumber - rel);
|
2013-12-13 07:25:30 +00:00
|
|
|
xt.append(tsn->secs + tsn->usecs/1000000.0);
|
|
|
|
ft.append(tsn->frame_number);
|
|
|
|
}
|
2019-08-14 08:18:51 +00:00
|
|
|
tlist = gxx_list_next(tlist);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2019-08-14 08:18:51 +00:00
|
|
|
listTSN = gxx_list_previous(listTSN);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QCPScatterStyle myScatter;
|
|
|
|
myScatter.setShape(QCPScatterStyle::ssCircle);
|
|
|
|
myScatter.setSize(3);
|
|
|
|
|
|
|
|
int graphcount = ui->sctpPlot->graphCount();
|
|
|
|
// create graph and assign data to it:
|
|
|
|
|
|
|
|
// Add TSN graph
|
|
|
|
if (xt.size() > 0) {
|
2013-12-17 09:51:34 +00:00
|
|
|
QCPGraph *gr = ui->sctpPlot->addGraph();
|
|
|
|
gr->setName(QString("TSN"));
|
2013-12-13 07:25:30 +00:00
|
|
|
myScatter.setPen(QPen(Qt::black));
|
|
|
|
myScatter.setBrush(Qt::black);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone);
|
|
|
|
ui->sctpPlot->graph(graphcount)->setData(xt, yt);
|
2013-12-17 10:22:00 +00:00
|
|
|
typeStrings.insert(graphcount, QString(tr("TSN")));
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-15 19:46:39 +00:00
|
|
|
void SCTPGraphDialog::drawGraph(const sctp_assoc_info_t* selected_assoc)
|
2013-12-13 07:25:30 +00:00
|
|
|
{
|
2018-08-15 19:46:39 +00:00
|
|
|
if (!selected_assoc) {
|
|
|
|
selected_assoc = SCTPAssocAnalyseDialog::findAssoc(this, selected_assoc_id);
|
|
|
|
if (!selected_assoc) return;
|
|
|
|
}
|
|
|
|
|
2014-02-19 14:39:13 +00:00
|
|
|
guint32 maxTSN, minTSN;
|
2013-12-13 07:25:30 +00:00
|
|
|
|
|
|
|
if (direction == 1) {
|
|
|
|
maxTSN = selected_assoc->max_tsn1;
|
2014-02-19 14:39:13 +00:00
|
|
|
minTSN = selected_assoc->min_tsn1;
|
2013-12-13 07:25:30 +00:00
|
|
|
} else {
|
|
|
|
maxTSN = selected_assoc->max_tsn2;
|
2014-02-19 14:39:13 +00:00
|
|
|
minTSN = selected_assoc->min_tsn2;
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2013-12-17 09:51:34 +00:00
|
|
|
ui->sctpPlot->clearGraphs();
|
2018-07-20 21:14:01 +00:00
|
|
|
xt.clear();
|
|
|
|
yt.clear();
|
|
|
|
xs.clear();
|
|
|
|
ys.clear();
|
|
|
|
xg.clear();
|
|
|
|
yg.clear();
|
|
|
|
xd.clear();
|
|
|
|
yd.clear();
|
|
|
|
xn.clear();
|
|
|
|
yn.clear();
|
|
|
|
ft.clear();
|
|
|
|
fs.clear();
|
|
|
|
fg.clear();
|
|
|
|
fd.clear();
|
|
|
|
fn.clear();
|
|
|
|
typeStrings.clear();
|
2018-06-06 09:57:21 +00:00
|
|
|
switch (type) {
|
2018-08-15 19:46:39 +00:00
|
|
|
case 1:
|
|
|
|
drawSACKGraph(selected_assoc);
|
|
|
|
drawNRSACKGraph(selected_assoc);
|
2013-12-13 07:25:30 +00:00
|
|
|
break;
|
2018-08-15 19:46:39 +00:00
|
|
|
case 2:
|
|
|
|
drawTSNGraph(selected_assoc);
|
2013-12-13 07:25:30 +00:00
|
|
|
break;
|
2018-08-15 19:46:39 +00:00
|
|
|
case 3:
|
|
|
|
drawTSNGraph(selected_assoc);
|
|
|
|
drawSACKGraph(selected_assoc);
|
|
|
|
drawNRSACKGraph(selected_assoc);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
drawTSNGraph(selected_assoc);
|
|
|
|
drawSACKGraph(selected_assoc);
|
|
|
|
drawNRSACKGraph(selected_assoc);
|
2013-12-13 07:25:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// give the axes some labels:
|
2013-12-17 10:22:00 +00:00
|
|
|
ui->sctpPlot->xAxis->setLabel(tr("time [secs]"));
|
|
|
|
ui->sctpPlot->yAxis->setLabel(tr("TSNs"));
|
2013-12-13 07:25:30 +00:00
|
|
|
ui->sctpPlot->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iSelectPlottables);
|
2021-10-10 18:42:51 +00:00
|
|
|
connect(ui->sctpPlot, &QCustomPlot::plottableClick, this, &SCTPGraphDialog::graphClicked);
|
2013-12-13 07:25:30 +00:00
|
|
|
// set axes ranges, so we see all data:
|
2014-02-19 14:39:13 +00:00
|
|
|
QCPRange myXRange(selected_assoc->min_secs, (selected_assoc->max_secs+1));
|
2018-06-06 09:57:21 +00:00
|
|
|
if (relative) {
|
2018-07-24 15:13:33 +00:00
|
|
|
QCPRange myYRange(0, maxTSN - minTSN + 1);
|
2018-06-06 09:57:21 +00:00
|
|
|
ui->sctpPlot->yAxis->setRange(myYRange);
|
|
|
|
} else {
|
2018-07-24 15:13:33 +00:00
|
|
|
QCPRange myYRange(minTSN, maxTSN + 1);
|
2018-06-06 09:57:21 +00:00
|
|
|
ui->sctpPlot->yAxis->setRange(myYRange);
|
|
|
|
}
|
2013-12-13 07:25:30 +00:00
|
|
|
ui->sctpPlot->xAxis->setRange(myXRange);
|
|
|
|
ui->sctpPlot->replot();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SCTPGraphDialog::on_pushButton_clicked()
|
|
|
|
{
|
2018-06-06 09:57:21 +00:00
|
|
|
type = 1;
|
|
|
|
drawGraph();
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SCTPGraphDialog::on_pushButton_2_clicked()
|
|
|
|
{
|
2018-06-06 09:57:21 +00:00
|
|
|
type = 2;
|
|
|
|
drawGraph();
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SCTPGraphDialog::on_pushButton_3_clicked()
|
|
|
|
{
|
2018-06-06 09:57:21 +00:00
|
|
|
type = 3;
|
|
|
|
drawGraph();
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SCTPGraphDialog::on_pushButton_4_clicked()
|
|
|
|
{
|
2018-08-15 19:46:39 +00:00
|
|
|
const sctp_assoc_info_t* selected_assoc = SCTPAssocAnalyseDialog::findAssoc(this, selected_assoc_id);
|
|
|
|
if (!selected_assoc) return;
|
|
|
|
|
2014-02-19 14:39:13 +00:00
|
|
|
ui->sctpPlot->xAxis->setRange(selected_assoc->min_secs, selected_assoc->max_secs+1);
|
2018-06-06 09:57:21 +00:00
|
|
|
if (relative) {
|
|
|
|
if (direction == 1) {
|
|
|
|
ui->sctpPlot->yAxis->setRange(0, selected_assoc->max_tsn1 - selected_assoc->min_tsn1);
|
|
|
|
} else {
|
|
|
|
ui->sctpPlot->yAxis->setRange(0, selected_assoc->max_tsn2 - selected_assoc->min_tsn2);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (direction == 1) {
|
|
|
|
ui->sctpPlot->yAxis->setRange(selected_assoc->min_tsn1, selected_assoc->max_tsn1);
|
|
|
|
} else {
|
|
|
|
ui->sctpPlot->yAxis->setRange(selected_assoc->min_tsn2, selected_assoc->max_tsn2);
|
|
|
|
}
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
ui->sctpPlot->replot();
|
|
|
|
}
|
|
|
|
|
2021-10-10 18:42:51 +00:00
|
|
|
void SCTPGraphDialog::graphClicked(QCPAbstractPlottable* plottable, int, QMouseEvent* event)
|
2013-12-13 07:25:30 +00:00
|
|
|
{
|
2013-12-17 09:51:34 +00:00
|
|
|
frame_num = 0;
|
|
|
|
int i=0;
|
|
|
|
double times = ui->sctpPlot->xAxis->pixelToCoord(event->pos().x());
|
|
|
|
if (plottable->name().contains("TSN", Qt::CaseInsensitive)) {
|
|
|
|
for (i = 0; i < xt.size(); i++) {
|
|
|
|
if (times <= xt.value(i)) {
|
|
|
|
frame_num = ft.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (plottable->name().contains("SACK", Qt::CaseInsensitive)) {
|
|
|
|
for (i = 0; i < xs.size(); i++) {
|
|
|
|
if (times <= xs.value(i)) {
|
|
|
|
frame_num = fs.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (plottable->name().contains("DUP", Qt::CaseInsensitive)) {
|
|
|
|
for (i = 0; i < xd.size(); i++) {
|
|
|
|
if (times <= xd.value(i)) {
|
|
|
|
frame_num = fd.at(i);
|
|
|
|
break;
|
|
|
|
}
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2013-12-17 09:51:34 +00:00
|
|
|
} else if (plottable->name().contains("NR_GAP", Qt::CaseInsensitive)) {
|
|
|
|
for (i = 0; i < xn.size(); i++) {
|
|
|
|
if (times <= xn.value(i)) {
|
|
|
|
frame_num = fn.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (plottable->name().contains("GAP", Qt::CaseInsensitive)) {
|
|
|
|
for (i = 0; i < xs.size(); i++) {
|
|
|
|
if (times <= xs.value(i)) {
|
|
|
|
frame_num = fs.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cap_file_ && frame_num > 0) {
|
|
|
|
cf_goto_frame(cap_file_, frame_num);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
2013-12-17 10:22:00 +00:00
|
|
|
ui->hintLabel->setText(QString(tr("<small><i>%1: %2 Time: %3 secs </i></small>"))
|
2013-12-13 07:25:30 +00:00
|
|
|
.arg(plottable->name())
|
2013-12-17 09:51:34 +00:00
|
|
|
.arg(floor(ui->sctpPlot->yAxis->pixelToCoord(event->pos().y()) + 0.5))
|
2013-12-13 07:25:30 +00:00
|
|
|
.arg(ui->sctpPlot->xAxis->pixelToCoord(event->pos().x())));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SCTPGraphDialog::save_graph(QDialog *dlg, QCustomPlot *plot)
|
|
|
|
{
|
|
|
|
QString file_name, extension;
|
Work around macOS running applications in /.
If an application is launched from the Finder, it appears to get / as
its current directory. This causes Wireshark open/save dialogs to open
up / if the user hasn't already opened a file in another directory, so
that there's no "last open directory" in the recent file.
Have get_persdatafile_dir(), on UN*X, cache the personal data directory
just as it does on Windows and, if nothing's been cached, have it fetch
the current directory and, if that succeeds *and* it's not the root
directory, use that. Otherwise, use the user's home directory.
Fixes #9862.
In addition, separate the notion of "last open directory" and "open
dialog initial directory", where the latter is the last open directory
*if* a file has been opened in this session or the recent file has the
last open directory from a previous session, otherwise it's the user's
personal data directory.
Use the latter notion in file open/save dialogs; use the former notion
when reading from and writing to the recent file.
This means we don't need to set the "last open directory" at startup
time. That way, running Wireshark without opening a file won't cause
the "last open directory" to be set, so that if a user runs it from a
directory, the "open dialog initial directory" won't be the last
directory from which Wireshark was run.
2023-11-10 08:08:48 +00:00
|
|
|
QDir path(mainApp->openDialogInitialDir());
|
2013-12-13 07:25:30 +00:00
|
|
|
QString pdf_filter = tr("Portable Document Format (*.pdf)");
|
|
|
|
QString png_filter = tr("Portable Network Graphics (*.png)");
|
|
|
|
QString bmp_filter = tr("Windows Bitmap (*.bmp)");
|
|
|
|
// Gaze upon my beautiful graph with lossy artifacts!
|
|
|
|
QString jpeg_filter = tr("JPEG File Interchange Format (*.jpeg *.jpg)");
|
|
|
|
QString filter = QString("%1;;%2;;%3;;%4")
|
|
|
|
.arg(pdf_filter)
|
|
|
|
.arg(png_filter)
|
|
|
|
.arg(bmp_filter)
|
|
|
|
.arg(jpeg_filter);
|
|
|
|
|
2022-02-01 03:30:09 +00:00
|
|
|
file_name = WiresharkFileDialog::getSaveFileName(dlg, mainApp->windowTitleString(tr("Save Graph As…")),
|
2013-12-13 07:25:30 +00:00
|
|
|
path.canonicalPath(), filter, &extension);
|
|
|
|
|
|
|
|
if (file_name.length() > 0) {
|
|
|
|
bool save_ok = false;
|
|
|
|
if (extension.compare(pdf_filter) == 0) {
|
|
|
|
save_ok = plot->savePdf(file_name);
|
|
|
|
} else if (extension.compare(png_filter) == 0) {
|
|
|
|
save_ok = plot->savePng(file_name);
|
|
|
|
} else if (extension.compare(bmp_filter) == 0) {
|
|
|
|
save_ok = plot->saveBmp(file_name);
|
|
|
|
} else if (extension.compare(jpeg_filter) == 0) {
|
|
|
|
save_ok = plot->saveJpg(file_name);
|
|
|
|
}
|
|
|
|
// else error dialog?
|
|
|
|
if (save_ok) {
|
2022-02-01 03:30:09 +00:00
|
|
|
mainApp->setLastOpenDirFromFilename(file_name);
|
2013-12-13 07:25:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCTPGraphDialog::on_saveButton_clicked()
|
|
|
|
{
|
|
|
|
save_graph(this, ui->sctpPlot);
|
|
|
|
}
|
2013-12-13 11:29:11 +00:00
|
|
|
|
2018-06-06 09:57:21 +00:00
|
|
|
void SCTPGraphDialog::on_relativeTsn_stateChanged(int arg1)
|
|
|
|
{
|
|
|
|
relative = arg1;
|
|
|
|
drawGraph();
|
|
|
|
}
|